bool StaticDiskPartitionInstance::GetBootDrivePath()

in source/code/scxsystemlib/disk/staticdiskpartitioninstance.cpp [364:570]


    bool StaticDiskPartitionInstance::GetBootDrivePath(wstring& bootpathStr)
    {
        SCX_LOGTRACE(m_log, L"DiskPartition::GetBootDrivePath():: Entering . . .");

        bootpathStr.clear();

        // buffer to store lines read from process output
        wstring curLine;
        wstring bootInterfacePath;

        // Determine Solaris boot disk using 'prtconf' and 'ls /dev/dsk'
        // cmdString stores the current process we are running via SCXProcess::Run()
#if defined(sparc)
#if PF_MAJOR == 5 && (PF_MINOR  == 9 || PF_MINOR == 10)
        wstring cmdPrtString = L"/usr/sbin/prtconf -pv"; 
#elif PF_MAJOR == 5 && PF_MINOR  == 11
        wstring cmdPrtString = L"/sbin/prtconf -pv"; 
#else
#error "Platform not supported"
#endif
#else// sparc
        wstring cmdPrtString = L"/usr/bin/grep bootpath /boot/solaris/bootenv.rc"; 
#endif

        std::string prtconfResult;
        std::string finalResult;
        std::istringstream processInputPrt;
        std::ostringstream processOutputPrt;
        std::ostringstream processErrPrt;

        try 
        {
            int retCode = m_deps->Run(cmdPrtString, processInputPrt, processOutputPrt, processErrPrt, 15000);
            if (retCode)
            {
                SCX_LOGERROR(m_log, L"Error returned from prtconf, unable to determine boot partition. Error code=" + StrFrom(retCode));
                return false;
            }
            prtconfResult = processOutputPrt.str();
            SCX_LOGTRACE(m_log, L"  Got this output from " + cmdPrtString + L" : " + StrFromUTF8(prtconfResult) );
            size_t lengthCaptured = prtconfResult.length();

            // Truncate trailing newline if there in captured output                  
            if (lengthCaptured > 0)
            {
                if (prtconfResult[lengthCaptured - 1] == '\n')
                {
                    prtconfResult[lengthCaptured - 1] = '\0';
                }
            }

        }
        catch(SCXCoreLib::SCXException &e)
        {
            SCX_LOGERROR(m_log, L"Unable to determine boot partition using prtconf ..." + e.What());
            return false;
        }

        SCXRegexPtr solPrtconfPatternPtr(NULL);

        std::vector<wstring> matchingVector;

        // Let's build our RegEx:
        try
        {
            SCX_LOGTRACE(m_log, L"  Using this regex on PrtConf output: " + c_SolPrtconfPattern );
            solPrtconfPatternPtr = new SCXCoreLib::SCXRegex(c_SolPrtconfPattern);
        }
        catch(SCXCoreLib::SCXInvalidRegexException &e)
        {
            SCX_LOGERROR(m_log, L"Exception caught in compiling regex: " + e.What());
            return false;
        }

        std::istringstream stringStrmPrtconf(prtconfResult);
        vector<wstring>  allLines;                       // all lines read from prtconf output
        allLines.clear();
        SCXStream::NLFs nlfs;
        SCXCoreLib::SCXStream::ReadAllLinesAsUTF8(stringStrmPrtconf, allLines, nlfs);

        for(vector<wstring>::iterator it = allLines.begin(); it != allLines.end(); it++)
        {
            curLine.assign(*it);
            matchingVector.clear();

            // Let's get the Boot partition interface and drive letter from prtconf
            if (solPrtconfPatternPtr->ReturnMatch(curLine, matchingVector, 0))
            {
                bootInterfacePath = matchingVector[1];
                SCX_LOGTRACE(m_log, L"Found match of PrtConfPattern : " + bootInterfacePath);
                break;
            }
        }

        if (bootInterfacePath.size() == 0)
        {
            std::wstringstream warningMsg;
            if (matchingVector.size() > 0)
            {
                warningMsg << L"Couldn't find Boot Partition, regular expression error message was: " << matchingVector[0];
            }
            else 
            {
                warningMsg << L"Couldn't find Boot Partition.";
            }
            SCX_LOG(m_log, suppressor.GetSeverity(warningMsg.str()), warningMsg.str());
            return false;
        }

        // Replace "disk" by "disk" or "sd" to normalize the boot interface path
        wstring from(L"disk");
        size_t start_pos = bootInterfacePath.find(from);
        if(start_pos != std::string::npos)
        {
            bootInterfacePath.replace(start_pos, from.length(), L"(disk|sd)");
        }

        wstring solLsPattern(c_SolLsPatternBeg);
        solLsPattern += bootInterfacePath;

        // Now we need to build up our pattern to find the bootdisk, using our results from above:
        SCXRegexPtr solLsPatternPtr(NULL);

        //Let's build our RegEx:
        try
        {
            SCX_LOGTRACE(m_log, L"  Using this regex on ls -l /dev/dsk output: " + solLsPattern );
            solLsPatternPtr = new SCXCoreLib::SCXRegex(solLsPattern);
        }
        catch(SCXCoreLib::SCXInvalidRegexException &e)
        {
            SCX_LOGERROR(m_log, L"Exception caught in compiling LS Pattern regex: " + e.What());
            return false;
        }

        // Retrieve the bootdrive using the bootInterface and driveLetter
        wstring cmdStringLs = L"/usr/bin/ls -l /dev/dsk";
        std::string devDskResult;

        std::istringstream processInputLs;
        std::ostringstream processOutputLs;
        std::ostringstream processErrLs;
        curLine.clear();

        try 
        {
            SCXCoreLib::SCXProcess::Run(cmdStringLs, processInputLs, processOutputLs, processErrLs, 15000);
            devDskResult = processOutputLs.str();
            SCX_LOGTRACE(m_log, L"  Got this output from " + cmdStringLs + L" : " + StrFromUTF8(devDskResult) );

            size_t lengthCaptured = devDskResult.length();

            // Truncate trailing newline if there in captured output
            if (lengthCaptured > 0)
            {
                if (devDskResult[lengthCaptured - 1] == '\n')
                {
                    devDskResult[lengthCaptured - 1] = '\0';
                }
            }

        }
        catch(SCXCoreLib::SCXException &e)
        {
            SCX_LOGERROR(m_log, L"Unable to determine boot partition..." + e.What());
            return false;
        }

        std::istringstream stringStrmDevDsk(devDskResult);
        allLines.clear();
        SCXCoreLib::SCXStream::ReadAllLinesAsUTF8(stringStrmDevDsk, allLines, nlfs);

        wstring bootDisk(L"");
        for(vector<wstring>::iterator it = allLines.begin(); it != allLines.end(); it++)
        {
            curLine.assign(*it);
            curLine.push_back('\n');
            matchingVector.clear();

            // Let's get the boot drive
            if (solLsPatternPtr->ReturnMatch(curLine, matchingVector, 0))
            {
                bootDisk = matchingVector[1];  //e.g. "c1t0d0s0"
                break;
            }
        }

        //Check the results
        if (bootDisk.size() == 0)
        {
            std::wstringstream warningMsg;
            if (matchingVector.size() > 0)
            {
                warningMsg << L"Couldn't find Boot Drive, regular expression error message was: " << matchingVector[0];
            }
            else
            {
                warningMsg << L"Couldn't find Boot Drive.";
            }
            SCX_LOG(m_log, suppressor.GetSeverity(warningMsg.str()), warningMsg.str());
            return false;
        }     

        bootpathStr = L"/dev/dsk/" + bootDisk; //e.g. "/dev/dsk/c1t0d0s0"

        return true;
    }