- Timestamp:
- Oct 8, 2010 8:26:59 AM (14 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp
r32976 r32997 35 35 #include <VBox/HostServices/GuestControlSvc.h> /* for PROC_STS_XXX */ 36 36 37 #include <VBox/log.h>38 37 #include <iprt/asm.h> 39 #include <iprt/assert.h> 40 #include <iprt/file.h> 38 #include <iprt/isofs.h> 41 39 #include <iprt/getopt.h> 42 #include <iprt/list.h>43 #include <iprt/path.h>44 #include <iprt/stream.h>45 #include <iprt/string.h>46 #include <iprt/time.h>47 #include <iprt/thread.h>48 40 49 41 #ifdef USE_XPCOM_QUEUE … … 558 550 } 559 551 560 #ifdef VBOX_WITH_COPYTOGUEST561 562 #define VBOX_ISO9660_MAX_SYSTEM_ID 32563 #define VBOX_ISO9660_MAX_VOLUME_ID 32564 #define VBOX_ISO9660_MAX_PUBLISHER_ID 128565 #define VBOX_ISO9660_MAX_VOLUME_ID 32566 #define VBOX_ISO9660_MAX_VOLUMESET_ID 128567 #define VBOX_ISO9660_MAX_PREPARER_ID 128568 #define VBOX_ISO9660_MAX_APPLICATION_ID 128569 #define VBOX_ISO9660_STANDARD_ID "CD001"570 #define VBOX_ISO9660_SECTOR_SIZE 2048571 572 #pragma pack(1)573 typedef struct VBoxISO9660DateShort574 {575 uint8_t year;576 uint8_t month;577 uint8_t day;578 uint8_t hour;579 uint8_t minute;580 uint8_t second;581 int8_t gmt_offset;582 } VBoxISO9660DateShort;583 584 typedef struct VBoxISO9660DateLong585 {586 char year[4];587 char month[2];588 char day[2];589 char hour[2];590 char minute[2];591 char second[2];592 char hseconds[2];593 int8_t gmt_offset;594 } VBoxISO9660DateLong;595 596 typedef struct VBoxISO9660DirRecord597 {598 uint8_t record_length;599 uint8_t extented_attr_length;600 uint32_t extent_location;601 uint32_t extent_location_big;602 uint32_t extent_data_length; /* Number of bytes (file) / len (directory). */603 uint32_t extent_data_length_big;604 VBoxISO9660DateShort date;605 uint8_t flags;606 uint8_t interleave_unit_size;607 uint8_t interleave_gap_size;608 uint16_t volume_sequence_number;609 uint16_t volume_sequence_number_big;610 uint8_t name_len;611 /* Starting here there will be the actual directory entry name612 * and a padding of 1 byte if name_len is odd. */613 } VBoxISO9660DirRecord;614 615 typedef struct VBoxISO9660PriVolDesc616 {617 uint8_t type;618 char name_id[6];619 uint8_t version;620 char system_id[VBOX_ISO9660_MAX_SYSTEM_ID];621 char volume_id[VBOX_ISO9660_MAX_VOLUME_ID];622 uint8_t unused2[8];623 uint32_t volume_space_size; /* Number of sectors, Little Endian. */624 uint32_t volume_space_size_big; /* Number of sectors Big Endian. */625 uint8_t unused3[32];626 uint16_t volume_set_size;627 uint16_t volume_set_size_big;628 uint16_t volume_sequence_number;629 uint16_t volume_sequence_number_big;630 uint16_t logical_block_size; /* 2048. */631 uint16_t logical_block_size_big;632 uint32_t path_table_size; /* Size in bytes. */633 uint32_t path_table_size_big; /* Size in bytes. */634 uint32_t path_table_start_first;635 uint32_t path_table_start_second;636 uint32_t path_table_start_first_big;637 uint32_t path_table_start_second_big;638 VBoxISO9660DirRecord root_directory_record;639 uint8_t directory_padding;640 char volume_set_id[VBOX_ISO9660_MAX_VOLUMESET_ID];641 char publisher_id[VBOX_ISO9660_MAX_PUBLISHER_ID];642 char preparer_id[VBOX_ISO9660_MAX_PREPARER_ID];643 char application_id[VBOX_ISO9660_MAX_APPLICATION_ID];644 char copyright_file_id[37];645 char abstract_file_id[37];646 char bibliographic_file_id[37];647 VBoxISO9660DateLong creation_date;648 VBoxISO9660DateLong modification_date;649 VBoxISO9660DateLong expiration_date;650 VBoxISO9660DateLong effective_date;651 uint8_t file_structure_version;652 uint8_t unused4[1];653 char application_data[512];654 uint8_t unused5[653];655 } VBoxISO9660PriVolDesc;656 657 typedef struct VBoxISO9660PathTableHeader658 {659 uint8_t length;660 uint8_t extended_attr_sectors;661 /** Sector of starting directory table. */662 uint32_t sector_dir_table;663 /** Index of parent directory (1 for the root). */664 uint16_t parent_index;665 /* Starting here there will be the name of the directory,666 * specified by length above. */667 } VBoxISO9660PathTableHeader;668 669 typedef struct VBoxISO9660PathTableEntry670 {671 char *path;672 char *path_full;673 VBoxISO9660PathTableHeader header;674 RTLISTNODE Node;675 } VBoxISO9660PathTableEntry;676 677 typedef struct VBoxISO9660File678 {679 RTFILE file;680 RTLISTNODE listPaths;681 VBoxISO9660PriVolDesc priVolDesc;682 } VBoxISO9660File;683 #pragma pack()684 685 void rtISO9660DestroyPathCache(VBoxISO9660File *pFile)686 {687 VBoxISO9660PathTableEntry *pNode = RTListNodeGetFirst(&pFile->listPaths, VBoxISO9660PathTableEntry, Node);688 while (pNode)689 {690 VBoxISO9660PathTableEntry *pNext = RTListNodeGetNext(&pNode->Node, VBoxISO9660PathTableEntry, Node);691 bool fLast = RTListNodeIsLast(&pFile->listPaths, &pNode->Node);692 693 if (pNode->path)694 RTStrFree(pNode->path);695 if (pNode->path_full)696 RTStrFree(pNode->path_full);697 RTListNodeRemove(&pNode->Node);698 RTMemFree(pNode);699 700 if (fLast)701 break;702 703 pNode = pNext;704 }705 }706 707 void RTISO9660Close(VBoxISO9660File *pFile)708 {709 if (pFile)710 {711 rtISO9660DestroyPathCache(pFile);712 RTFileClose(pFile->file);713 }714 }715 716 int rtISO9660AddToPathCache(PRTLISTNODE pList, const char *pszPath,717 VBoxISO9660PathTableHeader *pHeader)718 {719 AssertPtrReturn(pList, VERR_INVALID_PARAMETER);720 AssertPtrReturn(pszPath, VERR_INVALID_PARAMETER);721 AssertPtrReturn(pHeader, VERR_INVALID_PARAMETER);722 723 VBoxISO9660PathTableEntry *pNode = (VBoxISO9660PathTableEntry*)RTMemAlloc(sizeof(VBoxISO9660PathTableEntry));724 if (pNode == NULL)725 return VERR_NO_MEMORY;726 727 pNode->path = NULL;728 if (RT_SUCCESS(RTStrAAppend(&pNode->path, pszPath)))729 {730 memcpy((VBoxISO9660PathTableHeader*)&pNode->header,731 (VBoxISO9660PathTableHeader*)pHeader, sizeof(pNode->header));732 733 pNode->path_full = NULL;734 pNode->Node.pPrev = NULL;735 pNode->Node.pNext = NULL;736 RTListAppend(pList, &pNode->Node);737 return VINF_SUCCESS;738 }739 return VERR_NO_MEMORY;740 }741 742 int rtISO9660GetParentPathSub(PRTLISTNODE pList, VBoxISO9660PathTableEntry *pNode,743 char *pszPathNode, char **ppszPath)744 {745 int rc = VINF_SUCCESS;746 if (pNode->header.parent_index > 1)747 {748 uint16_t idx = 1;749 VBoxISO9660PathTableEntry *pNodeParent = RTListNodeGetFirst(pList, VBoxISO9660PathTableEntry, Node);750 while (idx++ < pNode->header.parent_index)751 pNodeParent = RTListNodeGetNext(&pNodeParent->Node, VBoxISO9660PathTableEntry, Node);752 char *pszPath;753 if (RTStrAPrintf(&pszPath, "%s/%s", pNodeParent->path, pszPathNode))754 {755 rc = rtISO9660GetParentPathSub(pList, pNodeParent, pszPath, ppszPath);756 RTStrFree(pszPath);757 }758 else759 rc = VERR_NO_MEMORY;760 }761 else762 {763 char *pszPath = RTStrDup(pszPathNode);764 *ppszPath = pszPath;765 }766 return rc;767 }768 769 /* Is a *flat* structure! */770 int rtISO9660UpdatePathCache(VBoxISO9660File *pFile)771 {772 AssertPtrReturn(pFile, VERR_INVALID_PARAMETER);773 rtISO9660DestroyPathCache(pFile);774 775 RTListInit(&pFile->listPaths);776 777 /* Seek to path tables. */778 int rc = VINF_SUCCESS;779 Assert(pFile->priVolDesc.path_table_start_first > 16);780 uint64_t uTableStart = (pFile->priVolDesc.path_table_start_first * VBOX_ISO9660_SECTOR_SIZE);781 Assert(uTableStart % VBOX_ISO9660_SECTOR_SIZE == 0); /* Make sure it's aligned. */782 if (RTFileTell(pFile->file) != uTableStart)783 rc = RTFileSeek(pFile->file, uTableStart, RTFILE_SEEK_BEGIN, &uTableStart);784 785 /*786 * Since this is a sequential format, for performance it's best to read the787 * complete path table (every entry can have its own level (directory depth) first788 * and the actual directories of the path table afterwards.789 */790 791 /* Read in the path table ... */792 uint32_t cbLeft = pFile->priVolDesc.path_table_size;793 VBoxISO9660PathTableHeader header;794 while ((cbLeft > 0) && RT_SUCCESS(rc))795 {796 size_t cbRead;797 rc = RTFileRead(pFile->file, (VBoxISO9660PathTableHeader*)&header, sizeof(VBoxISO9660PathTableHeader), &cbRead);798 if (RT_FAILURE(rc))799 break;800 cbLeft -= cbRead;801 if (header.length)802 {803 Assert(cbLeft >= header.length);804 Assert(header.length <= 31);805 /* Allocate and read in the actual path name. */806 char *pszName = RTStrAlloc(header.length + 1);807 rc = RTFileRead(pFile->file, (char*)pszName, header.length, &cbRead);808 if (RT_SUCCESS(rc))809 {810 cbLeft -= cbRead;811 pszName[cbRead] = '\0'; /* Terminate string. */812 /* Add entry to cache ... */813 rc = rtISO9660AddToPathCache(&pFile->listPaths, pszName, &header);814 }815 RTStrFree(pszName);816 /* Read padding if required ... */817 if ((header.length % 2) != 0) /* If we have an odd length, read/skip the padding byte. */818 {819 rc = RTFileSeek(pFile->file, 1, RTFILE_SEEK_CURRENT, NULL);820 cbLeft--;821 }822 }823 }824 825 /* Transform path names into full paths. This is a bit ugly right now. */826 VBoxISO9660PathTableEntry *pNode = RTListNodeGetLast(&pFile->listPaths, VBoxISO9660PathTableEntry, Node);827 while ( pNode828 && !RTListNodeIsFirst(&pFile->listPaths, &pNode->Node)829 && RT_SUCCESS(rc))830 {831 rc = rtISO9660GetParentPathSub(&pFile->listPaths, pNode,832 pNode->path, &pNode->path_full);833 if (RT_SUCCESS(rc))834 pNode = RTListNodeGetPrev(&pNode->Node, VBoxISO9660PathTableEntry, Node);835 }836 837 return rc;838 }839 840 int RTISO9660Open(const char *pszFileName, VBoxISO9660File *pFile)841 {842 AssertPtrReturn(pszFileName, VERR_INVALID_PARAMETER);843 AssertPtrReturn(pFile, VERR_INVALID_PARAMETER);844 845 RTListInit(&pFile->listPaths);846 #if 1847 Assert(sizeof(VBoxISO9660DateShort) == 7);848 Assert(sizeof(VBoxISO9660DateLong) == 17);849 int l = sizeof(VBoxISO9660DirRecord);850 RTPrintf("VBoxISO9660DirRecord=%ld\n", l);851 Assert(l == 33);852 /* Each volume descriptor exactly occupies one sector. */853 l = sizeof(VBoxISO9660PriVolDesc);854 RTPrintf("VBoxISO9660PriVolDesc=%ld\n", l);855 Assert(l == VBOX_ISO9660_SECTOR_SIZE);856 #endif857 int rc = RTFileOpen(&pFile->file, pszFileName, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE);858 if (RT_SUCCESS(rc))859 {860 uint64_t cbSize;861 rc = RTFileGetSize(pFile->file, &cbSize);862 if ( RT_SUCCESS(rc)863 && cbSize > 16 * VBOX_ISO9660_SECTOR_SIZE)864 {865 uint64_t cbOffset = 16 * VBOX_ISO9660_SECTOR_SIZE; /* Start reading at 32k. */866 size_t cbRead;867 VBoxISO9660PriVolDesc volDesc;868 bool fFoundPrimary = false;869 bool fIsValid = false;870 while (cbOffset < _1M)871 {872 /* Get primary descriptor. */873 rc = RTFileRead(pFile->file, (VBoxISO9660PriVolDesc*)&volDesc, sizeof(VBoxISO9660PriVolDesc), &cbRead);874 if (RT_FAILURE(rc) || cbRead < sizeof(VBoxISO9660PriVolDesc))875 break;876 if ( RTStrStr((char*)volDesc.name_id, VBOX_ISO9660_STANDARD_ID)877 && volDesc.type == 0x1 /* Primary Volume Descriptor */)878 {879 memcpy((VBoxISO9660PriVolDesc*)&pFile->priVolDesc,880 (VBoxISO9660PriVolDesc*)&volDesc, sizeof(VBoxISO9660PriVolDesc));881 fFoundPrimary = true;882 }883 else if(volDesc.type == 0xff /* Termination Volume Descriptor */)884 {885 if (fFoundPrimary)886 fIsValid = true;887 break;888 }889 cbOffset += sizeof(VBoxISO9660PriVolDesc);890 }891 892 if (fIsValid)893 rc = rtISO9660UpdatePathCache(pFile);894 else895 rc = VERR_INVALID_PARAMETER;896 }897 if (RT_FAILURE(rc))898 RTISO9660Close(pFile);899 }900 return rc;901 }902 903 /* Parses the extent content given at a specified sector. */904 int rtISO9660FindEntry(VBoxISO9660File *pFile, const char *pszFileName,905 uint32_t uExtentSector, uint32_t cbExtent /* Bytes */,906 VBoxISO9660DirRecord **ppRec)907 {908 AssertPtrReturn(pFile, VERR_INVALID_PARAMETER);909 Assert(uExtentSector > 16);910 911 int rc = RTFileSeek(pFile->file, uExtentSector * VBOX_ISO9660_SECTOR_SIZE,912 RTFILE_SEEK_BEGIN, NULL);913 if (RT_SUCCESS(rc))914 {915 rc = VERR_FILE_NOT_FOUND;916 917 uint8_t uBuffer[VBOX_ISO9660_SECTOR_SIZE];918 uint32_t cbLeft = cbExtent;919 while (!RT_SUCCESS(rc) && cbLeft > 0)920 {921 size_t cbRead;922 int rc2 = RTFileRead(pFile->file, (void*)&uBuffer, sizeof(uBuffer), &cbRead);923 Assert(RT_SUCCESS(rc2) && cbRead == VBOX_ISO9660_SECTOR_SIZE);924 cbLeft -= cbRead;925 926 uint32_t idx = 0;927 while (idx < cbRead)928 {929 VBoxISO9660DirRecord *pCurRecord = (VBoxISO9660DirRecord*)&uBuffer[idx];930 if (pCurRecord->record_length == 0)931 break;932 933 Assert(pCurRecord->name_len > 0);934 char *pszName = RTStrAlloc(pCurRecord->name_len + 1);935 AssertPtr(pszName);936 Assert(idx + sizeof(VBoxISO9660DirRecord) < cbRead);937 memcpy(pszName, &uBuffer[idx + sizeof(VBoxISO9660DirRecord)], pCurRecord->name_len);938 939 if ( pCurRecord->name_len == 1940 && pszName[0] == 0x0)941 {942 /* This is a "." directory (self). */943 }944 else if ( pCurRecord->name_len == 1945 && pszName[0] == 0x1)946 {947 /* This is a ".." directory (parent). */948 }949 else /* Regular directory or file */950 {951 if (pCurRecord->flags & RT_BIT(1)) /* Directory */952 {953 /* We don't recursively go into directories954 * because we already have the cached path table. */955 pszName[pCurRecord->name_len] = 0;956 /*rc = rtISO9660ParseDir(pFile, pszFileName,957 pDirHdr->extent_location, pDirHdr->extent_data_length);*/958 }959 else /* File */960 {961 /* Get last occurence of ";" and cut it off. */962 char *pTerm = strrchr(pszName, ';');963 if (pTerm)964 pszName[pTerm - pszName] = 0;965 966 /* Don't use case sensitive comparison here, in IS0 9660 all967 * file / directory names are UPPERCASE. */968 if (!RTStrICmp(pszName, pszFileName))969 {970 VBoxISO9660DirRecord *pRec = (VBoxISO9660DirRecord*)RTMemAlloc(sizeof(VBoxISO9660DirRecord));971 if (pRec)972 {973 memcpy(pRec, pCurRecord, sizeof(VBoxISO9660DirRecord));974 *ppRec = pRec;975 rc = VINF_SUCCESS;976 break;977 }978 else979 rc = VERR_NO_MEMORY;980 }981 }982 }983 idx += pCurRecord->record_length;984 }985 }986 }987 return rc;988 }989 990 int rtISO9660ResolvePath(VBoxISO9660File *pFile, const char *pszPath, uint32_t *puSector)991 {992 AssertPtrReturn(pFile, VERR_INVALID_PARAMETER);993 AssertPtrReturn(pszPath, VERR_INVALID_PARAMETER);994 AssertPtrReturn(puSector, VERR_INVALID_PARAMETER);995 996 int rc = VERR_FILE_NOT_FOUND;997 char *pszTemp = RTStrDup(pszPath);998 if (pszTemp)999 {1000 RTPathStripFilename(pszTemp);1001 1002 bool bFound = false;1003 VBoxISO9660PathTableEntry *pNode;1004 if (!RTStrCmp(pszTemp, ".")) /* Root directory? Use first node! */1005 {1006 pNode = RTListNodeGetFirst(&pFile->listPaths, VBoxISO9660PathTableEntry, Node);1007 bFound = true;1008 }1009 else1010 {1011 RTListForEach(&pFile->listPaths, pNode, VBoxISO9660PathTableEntry, Node)1012 {1013 if ( pNode->path_full != NULL /* Root does not have a path! */1014 && !RTStrICmp(pNode->path_full, pszTemp))1015 {1016 bFound = true;1017 break;1018 }1019 }1020 }1021 if (bFound)1022 {1023 *puSector = pNode->header.sector_dir_table;1024 rc = VINF_SUCCESS;1025 }1026 RTStrFree(pszTemp);1027 }1028 else1029 rc = VERR_NO_MEMORY;1030 return rc;1031 }1032 1033 int rtISO9660GetDirectoryRecord(VBoxISO9660File *pFile, const char *pszPath,1034 VBoxISO9660DirRecord **ppRecord)1035 {1036 AssertPtrReturn(pFile, VERR_INVALID_PARAMETER);1037 AssertPtrReturn(pszPath, VERR_INVALID_PARAMETER);1038 AssertPtrReturn(ppRecord, VERR_INVALID_PARAMETER);1039 1040 uint32_t uSector;1041 int rc = rtISO9660ResolvePath(pFile, pszPath, &uSector);1042 if (RT_SUCCESS(rc))1043 {1044 /* Seek and read the directory record of given file. */1045 rc = RTFileSeek(pFile->file, uSector * VBOX_ISO9660_SECTOR_SIZE,1046 RTFILE_SEEK_BEGIN, NULL);1047 if (RT_SUCCESS(rc))1048 {1049 size_t cbRead;1050 VBoxISO9660DirRecord *pRecord = (VBoxISO9660DirRecord*)RTMemAlloc(sizeof(VBoxISO9660DirRecord));1051 if (pRecord)1052 {1053 rc = RTFileRead(pFile->file, (VBoxISO9660DirRecord*)pRecord, sizeof(VBoxISO9660DirRecord), &cbRead);1054 if (RT_SUCCESS(rc))1055 {1056 Assert(cbRead == sizeof(VBoxISO9660DirRecord));1057 *ppRecord = pRecord;1058 }1059 if (RT_FAILURE(rc))1060 RTMemFree(pRecord);1061 }1062 else1063 rc = VERR_NO_MEMORY;1064 }1065 }1066 return rc;1067 }1068 1069 int RTISO9660GetFileInfo(VBoxISO9660File *pFile, const char *pszPath,1070 uint32_t *pcbOffset, uint32_t *pcbLength)1071 {1072 AssertPtrReturn(pFile, VERR_INVALID_PARAMETER);1073 AssertPtrReturn(pszPath, VERR_INVALID_PARAMETER);1074 AssertPtrReturn(pcbOffset, VERR_INVALID_PARAMETER);1075 1076 VBoxISO9660DirRecord *pDirRecord;1077 int rc = rtISO9660GetDirectoryRecord(pFile, pszPath, &pDirRecord);1078 if (RT_SUCCESS(rc))1079 {1080 /* Get actual file record. */1081 VBoxISO9660DirRecord *pFileRecord;1082 rc = rtISO9660FindEntry(pFile,1083 RTPathFilename(pszPath),1084 pDirRecord->extent_location,1085 pDirRecord->extent_data_length,1086 &pFileRecord);1087 if (RT_SUCCESS(rc))1088 {1089 *pcbOffset = pFileRecord->extent_location * VBOX_ISO9660_SECTOR_SIZE;1090 *pcbLength = pFileRecord->extent_data_length;1091 RTMemFree(pFileRecord);1092 }1093 RTMemFree(pDirRecord);1094 }1095 return rc;1096 }1097 1098 int RTISO9660ExtractFile(VBoxISO9660File *pFile, const char *pszSource,1099 const char *pszDest)1100 {1101 uint32_t cbOffset, cbLength;1102 int rc = RTISO9660GetFileInfo(pFile, pszSource, &cbOffset, &cbLength);1103 if (RT_SUCCESS(rc))1104 {1105 rc = RTFileSeek(pFile->file, cbOffset, RTFILE_SEEK_BEGIN, NULL);1106 if (RT_SUCCESS(rc))1107 {1108 RTFILE fileDest;1109 rc = RTFileOpen(&fileDest, pszDest, RTFILE_O_CREATE | RTFILE_O_WRITE | RTFILE_O_DENY_WRITE);1110 if (RT_SUCCESS(rc))1111 {1112 size_t cbToRead, cbRead, cbWritten;1113 uint8_t byBuffer[_4K];1114 while ( cbLength > 01115 && RT_SUCCESS(rc))1116 {1117 cbToRead = RT_MIN(cbLength, _4K);1118 rc = RTFileRead(pFile->file, (uint8_t*)byBuffer, cbToRead, &cbRead);1119 if (RT_FAILURE(rc))1120 break;1121 rc = RTFileWrite(fileDest, (uint8_t*)byBuffer, cbRead, &cbWritten);1122 if (RT_FAILURE(rc))1123 break;1124 cbLength -= cbRead;1125 }1126 RTFileClose(fileDest);1127 }1128 }1129 }1130 return rc;1131 }1132 1133 #endif1134 1135 552 static int handleCtrlCopyTo(HandlerArg *a) 1136 553 { 1137 VBoxISO9660Filefile;1138 int vrc = RTI SO9660Open("c:\\Downloads\\VBoxGuestAdditions_3.2.8.iso", &file);554 RTISOFSFILE file; 555 int vrc = RTIsoFsOpen(&file, "c:\\Downloads\\VBoxGuestAdditions_3.2.8.iso"); 1139 556 if (RT_SUCCESS(vrc)) 1140 557 { 1141 //vrc = RTISO9660ExtractFile(&file, "VBOXWINDOWSADDITIONS_X86.EXE", "C:\\VBOXWINDOWSADDITIONS_X86.EXE"); 1142 vrc = RTISO9660ExtractFile(&file, "32BIT/OS2/README.TXT", "C:\\OS2-Readme.txt"); 1143 RTISO9660Close(&file); 558 vrc = RTIsoFsExtractFile(&file, "VBOXWINDOWSADDITIONS_X86.EXE", "C:\\VBOXWINDOWSADDITIONS_X86.EXE"); 559 vrc = RTIsoFsExtractFile(&file, "FOO.EXE", "C:\\FOO.EXE"); 560 vrc = RTIsoFsExtractFile(&file, "32BIT/OS2/README.TXT", "C:\\OS2-Readme.txt"); 561 RTIsoFsClose(&file); 1144 562 } 1145 563 return vrc; -
trunk/src/VBox/Runtime/Makefile.kmk
r32990 r32997 387 387 r3/fs.cpp \ 388 388 r3/init.cpp \ 389 r3/isofs.cpp \ 389 390 r3/path.cpp \ 390 391 r3/process.cpp \
Note:
See TracChangeset
for help on using the changeset viewer.