Changeset 67381 in vbox for trunk/src/VBox/Runtime/common/fs/isomakercmd.cpp
- Timestamp:
- Jun 13, 2017 7:10:51 PM (8 years ago)
- svn:sync-xref-src-repo-rev:
- 116101
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/fs/isomakercmd.cpp
r67370 r67381 57 57 /** @name Name specifiers 58 58 * @{ */ 59 #define RTFSISOMAKERCMDNAME_PRIMARY_ISO RT_BIT_32(0) 60 #define RTFSISOMAKERCMDNAME_PRIMARY_ISO_ROCK_RIDGE RT_BIT_32(1) 61 #define RTFSISOMAKERCMDNAME_PRIMARY_ISO_TRANS_TBL RT_BIT_32(2) 62 #define RTFSISOMAKERCMDNAME_JOLIET RT_BIT_32(3) 63 #define RTFSISOMAKERCMDNAME_JOLIET_ROCK_RIDGE RT_BIT_32(4) 64 #define RTFSISOMAKERCMDNAME_JOLIET_TRANS_TBL RT_BIT_32(5) 65 #define RTFSISOMAKERCMDNAME_UDF RT_BIT_32(6) 66 #define RTFSISOMAKERCMDNAME_UDF_TRANS_TBL RT_BIT_32(7) 67 #define RTFSISOMAKERCMDNAME_HFS RT_BIT_32(8) 68 #define RTFSISOMAKERCMDNAME_HFS_TRANS_TBL RT_BIT_32(9) 59 #define RTFSISOMAKERCMDNAME_PRIMARY_ISO RTFSISOMAKER_NAMESPACE_ISO_9660 60 #define RTFSISOMAKERCMDNAME_JOLIET RTFSISOMAKER_NAMESPACE_JOLIET 61 #define RTFSISOMAKERCMDNAME_UDF RTFSISOMAKER_NAMESPACE_UDF 62 #define RTFSISOMAKERCMDNAME_HFS RTFSISOMAKER_NAMESPACE_HFS 63 64 #define RTFSISOMAKERCMDNAME_PRIMARY_ISO_ROCK_RIDGE RT_BIT_32(16) 65 #define RTFSISOMAKERCMDNAME_JOLIET_ROCK_RIDGE RT_BIT_32(17) 66 67 #define RTFSISOMAKERCMDNAME_JOLIET_TRANS_TBL RT_BIT_32(20) 68 #define RTFSISOMAKERCMDNAME_PRIMARY_ISO_TRANS_TBL RT_BIT_32(21) 69 #define RTFSISOMAKERCMDNAME_UDF_TRANS_TBL RT_BIT_32(22) 70 #define RTFSISOMAKERCMDNAME_HFS_TRANS_TBL RT_BIT_32(23) 69 71 70 72 #define RTFSISOMAKERCMDNAME_MAJOR_MASK \ 71 73 (RTFSISOMAKERCMDNAME_PRIMARY_ISO | RTFSISOMAKERCMDNAME_JOLIET | RTFSISOMAKERCMDNAME_UDF | RTFSISOMAKERCMDNAME_HFS) 74 72 75 #define RTFSISOMAKERCMDNAME_MINOR_MASK \ 73 76 ( RTFSISOMAKERCMDNAME_PRIMARY_ISO_ROCK_RIDGE | RTFSISOMAKERCMDNAME_PRIMARY_ISO_TRANS_TBL \ … … 75 78 | RTFSISOMAKERCMDNAME_UDF_TRANS_TBL \ 76 79 | RTFSISOMAKERCMDNAME_HFS_TRANS_TBL) 80 AssertCompile((RTFSISOMAKERCMDNAME_MAJOR_MASK & RTFSISOMAKERCMDNAME_MINOR_MASK) == 0); 77 81 /** @} */ 82 78 83 79 84 /********************************************************************************************************************************* … … 285 290 /** Pointer to a parsed name. */ 286 291 typedef RTFSISOMAKERCMDPARSEDNAME *PRTFSISOMAKERCMDPARSEDNAME; 292 /** Pointer to a const parsed name. */ 293 typedef RTFSISOMAKERCMDPARSEDNAME const *PCRTFSISOMAKERCMDPARSEDNAME; 287 294 288 295 … … 900 907 901 908 /** 909 * Adds a file. 910 * 911 * @returns IPRT status code. 912 * @param pOpts The ISO maker command instance. 913 * @param pszSrc The path to the source file. 914 * @param paParsedNames Array of parsed names, there are 915 * pOpts->cNameSpecifiers entries in the array. 916 */ 917 static int rtFsIsoMakerCmdAddFile(PRTFSISOMAKERCMDOPTS pOpts, const char *pszSrc, PCRTFSISOMAKERCMDPARSEDNAME paParsedNames) 918 { 919 uint32_t idxObj; 920 int rc = RTFsIsoMakerAddUnnamedFileWithSrcPath(pOpts->hIsoMaker, pszSrc, &idxObj); 921 if (RT_SUCCESS(rc)) 922 { 923 pOpts->cItemsAdded++; 924 925 for (uint32_t i = 0; i < pOpts->cNameSpecifiers; i++) 926 if (paParsedNames[i].cchPath > 0) 927 { 928 if (paParsedNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MAJOR_MASK) 929 { 930 rc = RTFsIsoMakerObjSetPath(pOpts->hIsoMaker, idxObj, 931 paParsedNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MAJOR_MASK, 932 paParsedNames[i].szPath); 933 if (RT_FAILURE(rc)) 934 { 935 rc = rtFsIsoMakerCmdErrorRc(pOpts, rc, "Error setting name '%s' on '%s': %Rrc", 936 paParsedNames[i].szPath, pszSrc, rc); 937 break; 938 } 939 } 940 if (paParsedNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MINOR_MASK) 941 { 942 /** @todo add APIs for this. */ 943 } 944 } 945 } 946 else 947 rc = rtFsIsoMakerCmdErrorRc(pOpts, rc, "Error adding '%s': %Rrc", pszSrc, rc); 948 return rc; 949 } 950 951 952 /** 902 953 * Processes a non-option argument. 903 954 * 904 * @returns 905 * @param pOpts .906 * @param pszSpec .955 * @returns IPRT status code. 956 * @param pOpts The ISO maker command instance. 957 * @param pszSpec The specification of what to add. 907 958 */ 908 959 static int rtFsIsoMakerCmdAddSomething(PRTFSISOMAKERCMDOPTS pOpts, const char *pszSpec) 909 960 { 910 961 const char * const pszSpecIn = pszSpec; 962 enum { kSpecialSrc_Normal, kSpecialSrc_Remove, kSpecialSrc_MustRemove } enmSpecialSrc = kSpecialSrc_Normal; 911 963 912 964 /* … … 917 969 for (;;) 918 970 { 919 const char *pszEqual = strchr(pszSpec, '='); 920 size_t cchName = pszEqual ? pszEqual - pszSpec : strlen(pszSpec); 921 if (cchName >= sizeof(aParsedNames[cParsedNames].szPath)) 971 const char *pszEqual = strchr(pszSpec, '='); 972 size_t cchName = pszEqual ? pszEqual - pszSpec : strlen(pszSpec); 973 bool fNeedSlash = pszEqual && !RTPATH_IS_SLASH(*pszSpec) && cchName > 0; 974 if (cchName + fNeedSlash >= sizeof(aParsedNames[cParsedNames].szPath)) 922 975 return rtFsIsoMakerCmdSyntaxError(pOpts, "name #%u (0-based) is too long: %s", cParsedNames, pszSpecIn); 923 976 if (cParsedNames >= pOpts->cNameSpecifiers + 1) 924 977 return rtFsIsoMakerCmdSyntaxError(pOpts, "too many names specified (max %u + source): %s", 925 978 pOpts->cNameSpecifiers, pszSpecIn); 926 memcpy(aParsedNames[cParsedNames].szPath, pszSpec, cchName); 979 if (!fNeedSlash) 980 memcpy(aParsedNames[cParsedNames].szPath, pszSpec, cchName); 981 else 982 { 983 memcpy(&aParsedNames[cParsedNames].szPath[1], pszSpec, cchName); 984 aParsedNames[cParsedNames].szPath[0] = RTPATH_SLASH; 985 cchName++; 986 } 927 987 aParsedNames[cParsedNames].szPath[cchName] = '\0'; 928 988 aParsedNames[cParsedNames].cchPath = (uint32_t)cchName; 929 989 cParsedNames++; 990 930 991 if (!pszEqual) 931 992 { 932 993 if (!cchName) 933 994 return rtFsIsoMakerCmdSyntaxError(pOpts, "empty source file name: %s", pszSpecIn); 995 if (cchName == 8 && strcmp(pszSpec, ":remove:") == 0) 996 enmSpecialSrc = kSpecialSrc_Remove; 997 else if (cchName == 13 && strcmp(pszSpec, ":must-remove:") == 0) 998 enmSpecialSrc = kSpecialSrc_MustRemove; 934 999 break; 935 1000 } … … 944 1009 aParsedNames[pOpts->cNameSpecifiers] = aParsedNames[cParsedNames - 1]; 945 1010 uint32_t iSrc = cParsedNames >= 2 ? cParsedNames - 2 : 0; 1011 1012 /* If the source is a input file name specifier, reduce it to something that starts with a slash. */ 1013 if (cParsedNames == 1) 1014 { 1015 if (RTVfsChainIsSpec(aParsedNames[iSrc].szPath)) 1016 { 1017 char *pszFinalPath; 1018 int rc = RTVfsChainQueryFinalPath(aParsedNames[iSrc].szPath, &pszFinalPath, NULL); 1019 if (RT_FAILURE(rc)) 1020 return rtFsIsoMakerCmdErrorRc(pOpts, rc, "RTVfsChainQueryFinalPath failed with %Rrc on: %s", rc, pszSpecIn); 1021 aParsedNames[iSrc].cchPath = (uint32_t)strlen(pszFinalPath); 1022 if (RTPATH_IS_SLASH(*pszFinalPath)) 1023 memcpy(aParsedNames[iSrc].szPath, pszFinalPath, aParsedNames[iSrc].cchPath + 1); 1024 else 1025 { 1026 memcpy(&aParsedNames[iSrc].szPath[1], pszFinalPath, aParsedNames[iSrc].cchPath + 1); 1027 aParsedNames[iSrc].szPath[0] = RTPATH_SLASH; 1028 aParsedNames[iSrc].cchPath++; 1029 } 1030 RTStrFree(pszFinalPath); 1031 } 1032 #if RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS 1033 else if ( RTPATH_IS_VOLSEP(aParsedNames[iSrc].szPath[1]) 1034 && RT_C_IS_ALPHA(aParsedNames[iSrc].szPath[0])) 1035 { 1036 if (RTPATH_IS_SLASH(aParsedNames[iSrc].szPath[2])) 1037 { 1038 memmove(&aParsedNames[iSrc].szPath[0], &aParsedNames[iSrc].szPath[2], aParsedNames[iSrc].cchPath - 1); 1039 aParsedNames[iSrc].cchPath -= 2; 1040 } 1041 else 1042 { 1043 memmove(&aParsedNames[iSrc].szPath[1], &aParsedNames[iSrc].szPath[2], aParsedNames[iSrc].cchPath - 1); 1044 aParsedNames[iSrc].szPath[0] = RTPATH_SLASH; 1045 aParsedNames[iSrc].cchPath -= 1; 1046 } 1047 } 1048 #endif 1049 else if (!RTPATH_IS_SLASH(aParsedNames[iSrc].szPath[0])) 1050 { 1051 if (aParsedNames[iSrc].cchPath + 2 > sizeof(aParsedNames[iSrc].szPath)) 1052 return rtFsIsoMakerCmdSyntaxError(pOpts, "name too long: %s", pszSpecIn); 1053 memmove(&aParsedNames[iSrc].szPath[1], &aParsedNames[iSrc].szPath[0], aParsedNames[iSrc].cchPath + 1); 1054 aParsedNames[iSrc].szPath[0] = RTPATH_SLASH; 1055 aParsedNames[iSrc].cchPath++; 1056 } 1057 } 1058 946 1059 for (uint32_t iDst = cParsedNames; iDst < pOpts->cNameSpecifiers; iDst++) 947 1060 aParsedNames[iDst] = aParsedNames[iSrc]; … … 949 1062 } 950 1063 951 /* Copy the specifier flags. */ 1064 /* 1065 * Copy the specifier flags and check that the paths all starts with slashes. 1066 */ 952 1067 for (uint32_t i = 0; i < pOpts->cNameSpecifiers; i++) 1068 { 953 1069 aParsedNames[i].fNameSpecifiers = pOpts->afNameSpecifiers[i]; 1070 Assert( aParsedNames[i].cchPath == 0 1071 || RTPATH_IS_SLASH(aParsedNames[i].szPath[0])); 1072 } 954 1073 955 1074 /* 956 1075 * Deal with special source filenames used to remove/change stuff. 957 1076 */ 958 const char * const pszSrc = aParsedNames[cParsedNames - 1].szPath;959 if (strcmp(pszSrc, ":remove:") == 0)1077 if ( enmSpecialSrc == kSpecialSrc_Remove 1078 || enmSpecialSrc == kSpecialSrc_MustRemove) 960 1079 { 961 1080 const char *pszFirstNm = NULL; 1081 uint32_t cRemoved = 0; 1082 for (uint32_t i = 0; i < pOpts->cNameSpecifiers; i++) 1083 if ( aParsedNames[i].cchPath > 0 1084 && (aParsedNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MAJOR_MASK)) 1085 { 1086 pszFirstNm = aParsedNames[i].szPath; 1087 uint32_t idxObj = RTFsIsoMakerGetObjIdxForPath(pOpts->hIsoMaker, 1088 aParsedNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MAJOR_MASK, 1089 aParsedNames[i].szPath); 1090 if (idxObj != UINT32_MAX) 1091 { 1092 int rc = RTFsIsoMakerObjRemove(pOpts->hIsoMaker, idxObj); 1093 if (RT_FAILURE(rc)) 1094 return rtFsIsoMakerCmdErrorRc(pOpts, rc, "Failed to remove '%s': %Rrc", pszSpecIn, rc); 1095 cRemoved++; 1096 } 1097 } 1098 if ( enmSpecialSrc == kSpecialSrc_MustRemove 1099 && cRemoved == 0) 1100 return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_FOUND, "Failed to locate '%s' for removal", pszSpecIn); 962 1101 } 1102 /* 1103 * Add regular source. 1104 */ 963 1105 else 964 1106 { 965 /* 966 * Regular source. 967 */ 968 1107 const char *pszSrc = aParsedNames[cParsedNames - 1].szPath; 1108 RTFSOBJINFO ObjInfo; 1109 uint32_t offError; 1110 RTERRINFOSTATIC ErrInfo; 1111 int rc = RTVfsChainQueryInfo(pszSrc, &ObjInfo, RTFSOBJATTRADD_UNIX, 1112 RTPATH_F_FOLLOW_LINK, &offError, RTErrInfoInitStatic(&ErrInfo)); 1113 if (RT_FAILURE(rc)) 1114 return rtFsIsoMakerCmdErrorRc(pOpts, rc, "Error query info on '%s': %Rrc", pszSrc, rc); 1115 if (RTFS_IS_FILE(ObjInfo.Attr.fMode)) 1116 return rtFsIsoMakerCmdAddFile(pOpts, pszSrc, aParsedNames); 1117 if (RTFS_IS_DIRECTORY(ObjInfo.Attr.fMode)) 1118 return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_IMPLEMENTED, "Adding directory '%s' failed: not implemented", pszSpecIn); 1119 if (RTFS_IS_SYMLINK(ObjInfo.Attr.fMode)) 1120 return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_IMPLEMENTED, "Adding symlink '%s' failed: not implemented", pszSpecIn); 1121 return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_IMPLEMENTED, "Adding special file '%s' failed: not implemented", pszSpecIn); 969 1122 } 970 1123 … … 997 1150 Opts.pErrInfo = pErrInfo; 998 1151 Opts.fVirtualImageMaker = phVfsFile != NULL; 1152 Opts.cNameSpecifiers = 1; 1153 Opts.afNameSpecifiers[0] = RTFSISOMAKERCMDNAME_MAJOR_MASK; 1154 Opts.fDstNamespaces = RTFSISOMAKERCMDNAME_MAJOR_MASK; 999 1155 if (phVfsFile) 1000 1156 *phVfsFile = NIL_RTVFSFILE;
Note:
See TracChangeset
for help on using the changeset viewer.