host/common/linux/portablehelpersminor.cpp (1,690 lines of code) (raw):
#include "portablehelpers.h"
#include "portablehelperscommonheaders.h"
#include "portablehelpersmajor.h"
#include "portablehelpersminor.h"
#include "inmdefines.h"
#include "configwrapper.h"
#include "inmsafecapis.h"
#include "inmsafeint.h"
#include "inmageex.h"
#include <mntent.h>
#include <fstab.h>
#include <linux/fs.h>
#include <sys/utsname.h>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <string>
#include <vector>
#include <set>
#include <algorithm>
#include <fstream>
#include <sstream>
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <limits.h>
#include <dirent.h>
#include <fcntl.h>
#include<boost/shared_ptr.hpp>
#include <boost/shared_array.hpp>
#include "file.h"
#define THRSHOLD_NUM_FIELDSINFSTAB 4
#define FLAG_FIELD_IN_FSTAB 3
bool ShouldCollectNicInfo(const int &sockfd, struct ifreq *pifr, const char *ipaddr);
void GetNetIfParameters(const std::string &ifrName, std::string& hardwareAddress, std::string &netmask);
bool FillNicInfos(const int &sockfd, struct ifconf *pifc, size_t sizeofifreq, NicInfos_t & nicInfos);
void InsertNicInfo(NicInfos_t &nicInfos, const std::string &name, const std::string &hardwareaddress, const std::string &ipaddress,
const std::string &netmask, const E_INM_TRISTATE &isdhcpenabled);
void UpdateNicInfoAttr(const std::string &attr, const std::string &value, NicInfos_t &nicinfos);
void GetNicNamesFromProc(std::set<std::string> &nicnamesfromproc);
bool getDHCPValue( std::string interface, std::string& value );
/* LINUX SPECIFIC */
SVERROR GetVolSize(ACE_HANDLE handle, unsigned long long *pSize)
{
unsigned long nsec;
unsigned long long sz = 0ULL;
if (handle == ACE_INVALID_HANDLE || pSize == NULL)
{
return EINVAL;
}
if (ioctl(handle, BLKGETSIZE, &nsec))
{
nsec = 0;
}
if (ioctl(handle, BLKGETSIZE64, &sz))
{
sz = 0;
}
if (sz == 0 || sz == nsec)
{
sz = ((unsigned long long) nsec) * 512;
}
*pSize = sz;
return SVS_OK;
}
/* LINUX SPECIFIC : BUT CAN BE MADE COMMON TO UNIX */
SVERROR GetFsVolSize(const char *volName, unsigned long long *pfsSize)
{
if (pfsSize == NULL) {
DebugPrintf(SV_LOG_ERROR, "GetFsVolSize() failed, err = EINVAL\n");
return SVE_FAIL;
}
SVERROR res = SVS_OK;
int fd;
if ((fd = open(volName, O_RDONLY))< 0)
{
res = SVE_FAIL;
}
else if (GetVolSize(fd, pfsSize).failed())
{
res = SVE_FAIL;
}
close(fd);
return res;
}
/* LINUX SPECIFIC */
SVERROR GetFsSectorSize(const char *volName, unsigned int *psectorSize)
{
if (psectorSize == NULL) {
DebugPrintf(SV_LOG_ERROR, "GetFsVolSize() failed, err = EINVAL\n");
return SVE_FAIL;
}
unsigned int sector_size = 512;
int ssize;
int fd;
if ((fd = open(volName, O_RDONLY))< 0)
return SVE_FAIL;
if(ioctl(fd, BLKSSZGET, &ssize) == 0)
sector_size = (unsigned int)ssize;
close(fd);
*psectorSize = sector_size;
return SVS_OK;
}
/* LINUX SPECIFIC */
SVERROR GetHardwareSectorSize(ACE_HANDLE handleVolume, unsigned int *pSectSize)
{
SVERROR sve = SVS_OK;
unsigned int sector_size = 0;
do
{
if (pSectSize == NULL || handleVolume == ACE_INVALID_HANDLE)
{
sve = EINVAL;
DebugPrintf( SV_LOG_ERROR, "@ LINE %d in FILE %s \n", __LINE__, __FILE__ );
DebugPrintf( SV_LOG_ERROR, "FAILED GetHardwareSectorSize, err = EINVAL\n");
break;
}
int ssize;
if(ioctl(handleVolume, BLKSSZGET, &ssize) == 0)
sector_size = (unsigned int)ssize;
else
sector_size = 512;
} while (FALSE);
if (!sve.failed())
*pSectSize = sector_size;
return sve;
}
/* LINUX SPECIFIC */
/*
* FUNTION NAME : removeFSEntry
*
* DESCRIPTION :
*
* This is a lowlevel function of DeleteFSEnt() which takes the fstab entries and
* the device name on which the operation is performed, deletes the matching
* readonly or default entries for this device, comments the maching entries which
* contain other flags like noexec,nosuid. It leaves the other entries as they are
*
* ALGORITHM :
*
* for each entry fsent in fsents
* if the device name or label matches
* if the flags contain 'ro' OR only 'defaults' OR only 'rw'
* skip this entry
* else
* comment this entry
* else write the entry as it is
*
* INPUT PARAMETERS :
*
* device : name of the device on which action is performed
* label : lable of the device on which action is performed
* fsents : contains all the entries in the fstab file
*
* OUTPUT PARAMETERS :
*
* fsents : contains the modified entries after the operation is performed
*
* RETURN VALUE : true if succeeds false otherwise.
*/
bool removeFSEntry(const std::string& device, const std::string& label, std::vector<std::string>& fsents)
{
bool rv=true;
std::string realDevice = device;
GetDeviceNameFromSymLink(realDevice);
std::vector<std::string>::iterator fsent_iter = fsents.begin();
std::vector<std::string>::iterator fsent_end = fsents.end();
std::vector<std::string> tempFSEnts;
for(; fsent_iter != fsent_end; ++fsent_iter)
{
std::string fsent = *fsent_iter;
svector_t fields;
Tokenize(fsent, fields, " \t\n");
if(fields.size()<THRSHOLD_NUM_FIELDSINFSTAB)
{
tempFSEnts.push_back(fsent);
continue;
}
std::string fstab_dev = fields[0];
std::string fstab_flags = fields[FLAG_FIELD_IN_FSTAB];
svector_t flags = split(fstab_flags, "," );
if(fstab_dev.find("LABEL=",0) != std::string::npos)
{
if(!label.empty() && (label == fstab_dev))
{//if the lable matches this fstab entry
if( (find(flags.begin(), flags.end(), "ro") != flags.end()) ||
((find(flags.begin(), flags.end(), "rw") != flags.end()) && (flags.size() == 1)) ||
((find(flags.begin(), flags.end(), "defaults") != flags.end()) && (flags.size() == 1)) )
;//do not include this entry. equivalent to deleting.
else
{
std::string tempFSEnt = "#" + *fsent_iter;
tempFSEnts.push_back(tempFSEnt);
}
}
else
{//if the lable doesnt match this fstab entry we write it as it is.
tempFSEnts.push_back(fsent);
}
}
else if(GetDeviceNameFromSymLink(fstab_dev) && (fstab_dev == realDevice))
{//if the device matches this fstab entry
if( (find(flags.begin(), flags.end(), "ro") != flags.end()) ||
((find(flags.begin(), flags.end(), "rw") != flags.end()) && (flags.size() == 1)) ||
((find(flags.begin(), flags.end(), "defaults") != flags.end()) && (flags.size() == 1)) )
;//do not include this entry. equivalent to deleting.
else
{
std::string tempFSEnt = "#" + *fsent_iter;
tempFSEnts.push_back(tempFSEnt);
}
}
else
{//if the entry does not match the device or lable we are looking write it as it is.
tempFSEnts.push_back(fsent);
}
} // for loop
fsents.assign(tempFSEnts.begin(),tempFSEnts.end());
return rv;
}
/* LINUX SPECIFIC */
/*
* FUNTION NAME : addRWFSEntry
*
* DESCRIPTION :
*
* This is a lowlevel function for AddFSEnt() which takes the fstab entries and the
* device name on which the operation is performed and uncomments the maching commented
* entry OR adds a new one
*
* ALGORITHM :
*
* call removeFSEntry for this device. //This cleans the old entries which may not be needed
* for each entry fsent in fsents
* if this is a commented entry
* if the device/label maches
* if the filesystem type maches
* uncomment this entry
* else
* delete this entry //as the file system changed we cant use this
* else
* write the entry as it is
* else
* write the entry as it is
* //end of for
* if we did not uncomment any existing entry ans a new one
*
* INPUT PARAMETERS :
*
* device : name of the device on which action is performed
* label : lable of the device on which action is performed
* mountpoint: mountpoint for the device being mounted
* type : filesystem type contained in the device being mounted
* fsents : contains all the entries in the fstab file
*
* OUTPUT PARAMETERS :
*
* fsents : contains the modified entries after the operation is performed
*
* RETURN VALUE : true if succeeds false otherwise.
*/
bool addRWFSEntry(const std::string& device, const std::string& label, const std::string& mountpoint,
const std::string& type,
std::vector<std::string>& fsents)
{
bool rv=true;
do
{
if(!removeFSEntry(device, label, fsents))
{
rv =false;
break;
}
std::string realDevice = device;
GetDeviceNameFromSymLink(realDevice);
std::vector<std::string>::iterator fsent_iter = fsents.begin();
std::vector<std::string>::iterator fsent_end = fsents.end();
std::vector<std::string> tempFSEnts;
bool addNewEntry = true;
for(; fsent_iter != fsent_end; ++fsent_iter)
{
std::string fsent = *fsent_iter;
svector_t fields;
Tokenize(fsent, fields, " \t\n");
if(fields.size() <6)
{
tempFSEnts.push_back(fsent);
continue;
}
// case: commented entry
std::string field1 = fields[0];
if(field1[0] == '#' )
{
std::string fstab_dev(fields[0].begin()+1, fields[0].end());
std::string fstab_mnt = fields[1];
std::string fstab_type = fields[2];
std::string fstab_flags = fields[3];
std::string fstab_dump = fields[4];
std::string fstab_fsck = fields[5];
// non Label entry
if(fstab_dev.find("LABEL=",0) == std::string::npos)
{
// case: special device entries like none or swap
if(!GetDeviceNameFromSymLink(fstab_dev))
{
tempFSEnts.push_back(fsent);
continue;
}
// case: non matching entry
if(fstab_dev != realDevice)
{
tempFSEnts.push_back(fsent);
continue;
}
}
else
{
// case: label entry, non matching lavel
if(!label.empty() && label != fstab_dev)
{
tempFSEnts.push_back(fsent);
continue;
}
}
// case: commented entry matching device and fs
if(type == fstab_type)
{
if(mountpoint == "" || mountpoint == fstab_mnt)
{
//mounting rw with no mountpoint specified or mounting at previous location; uncomment
std::string uncommentedfsent(fsent.begin()+1, fsent.end());
tempFSEnts.push_back(uncommentedfsent);
}
else
{
//mounting rw with new mountpoint
std::string uncommentedfsent = fstab_dev + "\t\t" + mountpoint + "\t\t" + fstab_type + "\t" +
fstab_flags + "\t\t" + fstab_dump + " " + fstab_fsck + "\n";
tempFSEnts.push_back(uncommentedfsent);
}
//Dont add new entry
addNewEntry = false;
}
else // case: commented entry matching device, fs changed
{
;//do not push this entry as there is filesystem doesnt match. equivalent to delete.
}
}
else // case: uncommented entries
{
//write all uncommented entries as they are.
tempFSEnts.push_back(fsent);
}
}
if(fsent_iter != fsent_end)
{
rv = false;
break;
}
if(!rv)
break;
// if there were no matching commented entries for this in the fstab, create new one
if(addNewEntry)
{
std::string newFSEntry;
if(!label.empty())
newFSEntry=label;
else
newFSEntry=device;
newFSEntry+="\t\t" + mountpoint + "\t\t" + type + "\t" + "rw " + "\t\t" + "0" + " " + "0" + "\n";
tempFSEnts.push_back(newFSEntry);
}
fsents.assign(tempFSEnts.begin(),tempFSEnts.end());
}while(false);
return rv;
}
/* LINUX SPECIFIC */
/*
* FUNTION NAME : addROFSEntry
*
* DESCRIPTION :
*
* This is a lowlevel function of AddFSEnt() which takes the fstab entries and
* the device name on which the operation is performed and simply adds a new
* readonly entry
*
* ALGORITHM :
*
* call removeFSEntry for this device. //This cleans the old entries which may
* not be needed append a new readonly entry to the existing fsents
*
* INPUT PARAMETERS :
*
* device : name of the device on which action is performed
* label : lable of the device on which action is performed
* mountpoint: mountpoint for the device being mounted
* type : filesystem type contained in the device being mounted
* fsents : contains all the entries in the fstab file
*
* OUTPUT PARAMETERS :
*
* fsents : contains the modified entries after the operation is performed
*
* RETURN VALUE : true if succeeds false otherwise.
*/
bool addROFSEntry(const std::string& device, const std::string& label, const std::string& mountpoint,
const std::string& type,
std::vector<std::string>& fsents)
{
bool rv=true;
do
{
if(!removeFSEntry(device, label, fsents))
{
rv =false;
break;
}
std::string newFSEntry;
if(!label.empty())
newFSEntry=label;
else
newFSEntry=device;
newFSEntry+="\t\t" + mountpoint + "\t\t" + type + "\t" + "ro " + "\t\t" + "0" + " " + "0" + "\n";
fsents.push_back(newFSEntry);
}while(false);
return rv;
}
/* LINUX SPECIFIC */
bool MountDevice(const std::string& device,const std::string& mountPoint,const std::string& fsType,bool bSetReadOnly, int &exitCode,std::string &errorMsg)
{
bool rv = true;
do
{
if ( mountPoint.empty())
{
std::stringstream strerr;
strerr << "Empty mountpoint specified.";
strerr << "Cannot mount device " << device << "\n";
DebugPrintf(SV_LOG_ERROR,"%s", strerr.str().c_str());
errorMsg = strerr.str();
rv = false;
break;
}
std::string errmsg;
if(!IsValidMountPoint(mountPoint,errmsg))
{
std::stringstream strerr;
strerr << "Cannot mount device " << device << " on mount point " << mountPoint << ". " << errmsg << "\n";
DebugPrintf(SV_LOG_ERROR,"%s", strerr.str().c_str());
errorMsg = strerr.str();
rv = false;
break;
}
bool bCanMount = false;
bool remount = false;
std::string flag;
if(bSetReadOnly)
flag="ro ";
else
flag="rw ";
std::string sFileSystem = fsType;
if(sFileSystem =="")
sFileSystem ="auto";
std::string flags = flag; //This is used only in case of Uncomment FSTAB. flag gets updated with -o remount where as flags doesn't.
std::string sMount = "";
std::string mode;
if ( IsVolumeMounted(device,sMount,mode))
{
if ( sMount == mountPoint) //need to check if mode is same or not. If the mode is same, we will say already mounted, else we will do ewmount
{
bCanMount = true;
flag+=" -o remount";
}
else
{
bCanMount = false;
std::stringstream strerr;
strerr << "Failed to unhide volume, since volume is already visible on mount " << sMount;
strerr << " and requested mount is " << mountPoint;
strerr << ".Ensure system mounts are not specified.\n";
DebugPrintf(SV_LOG_ERROR,"%s", strerr.str().c_str());
errorMsg = strerr.str();
rv = false;
break;
}
}
else /* volume is not mounted */
{
bCanMount = true;
}
if ( bCanMount)
{
sFileSystem = ToLower(sFileSystem);
if(!strcmp(sFileSystem.c_str(),"fat32")) {
sFileSystem = "vfat";
}else if(!strcmp(sFileSystem.c_str(),"fat")) {
sFileSystem = "msdos";
}else if(!strcmp(sFileSystem.c_str(),"pcfs")) {
sFileSystem = "vfat";
}
/*
PR# 3079:
if the fs is ntfs
open the volume in rw mode
read the magic number
if it is not ntfs
log a message
write ntfs
end if
*/
if (!strcmp(sFileSystem.c_str(),"ntfs"))
{
ACE_HANDLE hVolume = ACE_OS::open(device.c_str(), O_RDWR, FILE_SHARE_READ);
do
{
SVERROR sve;
if(ACE_INVALID_HANDLE == hVolume)
{
sve = ACE_OS::last_error();
DebugPrintf( SV_LOG_ERROR, "@ LINE %d in FILE %s \n", __LINE__, __FILE__ );
std::stringstream strerr;
strerr << "ACE_OS::open failed on " << device;
strerr << " in MountVolume.err = " << sve.toString() << "\n";
DebugPrintf(SV_LOG_ERROR,"%s", strerr.str().c_str());
errorMsg = strerr.str();
exitCode = ACE_OS::last_error();
break;
}
#ifndef LLSEEK_NOT_SUPPORTED
if (ACE_OS::llseek(hVolume, SV_NTFS_MAGIC_OFFSET, SEEK_SET) < 0) {
#else
if (ACE_OS::lseek(hVolume, SV_NTFS_MAGIC_OFFSET, SEEK_SET) < 0) {
#endif
sve = ACE_OS::last_error();
DebugPrintf(SV_LOG_ERROR,"@ LINE %d in FILE %s \n", __LINE__, __FILE__ );
std::stringstream strerr;
strerr << "FAILED ACE_OS::llseek on " << device;
strerr << ", err = " << sve.toString() << "\n";
DebugPrintf(SV_LOG_ERROR,"%s", strerr.str().c_str());
errorMsg = strerr.str();
exitCode = ACE_OS::last_error();
break;
}
char pchDeltaBuffer[SV_FSMAGIC_LEN +1];
long cbRead = ACE_OS::read(hVolume, pchDeltaBuffer,SV_FSMAGIC_LEN);
if(cbRead != SV_FSMAGIC_LEN)
{
sve = ACE_OS::last_error();
DebugPrintf(SV_LOG_ERROR,"@ LINE %d in FILE %s \n", __LINE__, __FILE__ );
std::stringstream strerr;
strerr << "FAILED ACE_OS::read on " << device;
strerr << ", err = " << sve.toString() << "\n";
DebugPrintf(SV_LOG_ERROR,"%s", strerr.str().c_str());
errorMsg = strerr.str();
exitCode = ACE_OS::last_error();
break;
}
if(0 != memcmp(&pchDeltaBuffer[0],SV_MAGIC_NTFS, SV_FSMAGIC_LEN))
{
DebugPrintf(SV_LOG_ERROR, "%s did not have ntfs header. adding it manually\n", device.c_str());
inm_memcpy_s(pchDeltaBuffer, sizeof(pchDeltaBuffer), SV_MAGIC_NTFS, SV_FSMAGIC_LEN);
#ifndef LLSEEK_NOT_SUPPORTED
if (ACE_OS::llseek(hVolume, SV_NTFS_MAGIC_OFFSET, SEEK_SET) < 0) {
#else
if (ACE_OS::lseek(hVolume, SV_NTFS_MAGIC_OFFSET, SEEK_SET) < 0) {
#endif
sve = ACE_OS::last_error();
DebugPrintf(SV_LOG_ERROR,"@ LINE %d in FILE %s \n", __LINE__, __FILE__ );
std::stringstream strerr;
strerr << "FAILED ACE_OS::llseek on " << device;
strerr << ", err = " << sve.toString() << "\n";
DebugPrintf(SV_LOG_ERROR,"%s", strerr.str().c_str());
errorMsg = strerr.str();
exitCode = ACE_OS::last_error();
break;
}
long cbWrite = ACE_OS::write(hVolume,&pchDeltaBuffer[0],SV_FSMAGIC_LEN);
if(cbWrite != SV_FSMAGIC_LEN)
{
sve = ACE_OS::last_error();
DebugPrintf(SV_LOG_ERROR,"@ LINE %d in FILE %s \n", __LINE__, __FILE__ );
std::stringstream strerr;
strerr << "FAILED ACE_OS::write on " << device;
strerr << ", err = " << sve.toString() << "\n";
DebugPrintf(SV_LOG_ERROR,"%s", strerr.str().c_str());
errorMsg = strerr.str();
exitCode = ACE_OS::last_error();
break;
}
}
} while (0);
if(ACE_INVALID_HANDLE != hVolume)
{
ACE_OS::close(hVolume);
hVolume = ACE_INVALID_HANDLE;
}
} // end if strcmp ntfs
std::string fsmount;
fsmount+="mount ";
fsmount+=device.c_str() ;
fsmount+=" ";
fsmount+=mountPoint.c_str() ;
fsmount+=" ";
fsmount+="-t ";
fsmount+=sFileSystem.c_str();
fsmount+=" ";
fsmount+="-o ";
fsmount+=flag ;
if(flag!=flags)
remount=true;
// Bug: 7329
std::string displayErrorMsg;
displayErrorMsg = "Tried with fstype: ";
displayErrorMsg += sFileSystem;
int cmdExitCode, retryExitCode;
std::string cmdErrorMsg, retryErrorMsg;
if(!ExecuteInmCommand(fsmount,cmdErrorMsg,cmdExitCode))
{
sFileSystem = ToUpper(sFileSystem);
fsmount.clear();
fsmount+="mount ";
fsmount+=device.c_str() ;
fsmount+=" ";
fsmount+=mountPoint.c_str() ;
fsmount+=" ";
fsmount+="-t ";
fsmount+=sFileSystem.c_str();
fsmount+=" ";
fsmount+="-o ";
fsmount+=flag;
if(!ExecuteInmCommand(fsmount,retryErrorMsg,retryExitCode))
{
if((cmdExitCode == retryExitCode) && (!stricmp(retryErrorMsg.c_str(),cmdErrorMsg.c_str())))
{
displayErrorMsg += ", ";
displayErrorMsg += sFileSystem;
displayErrorMsg += "\n";
displayErrorMsg += "Unhide mount operation failed\n";
displayErrorMsg += retryErrorMsg;
}
else
{
displayErrorMsg += "\n";
displayErrorMsg += "Unhide mount operation failed\n";
displayErrorMsg += cmdErrorMsg;
displayErrorMsg += " Tried with fstype: ";
displayErrorMsg += sFileSystem;
displayErrorMsg += "\n";
displayErrorMsg += "Unhide mount operation failed\n";
displayErrorMsg += retryErrorMsg;
}
DebugPrintf(SV_LOG_ERROR,"%s\n",displayErrorMsg.c_str());
errorMsg = displayErrorMsg;
exitCode = cmdExitCode;
rv = false;
break;
}
}
}
}while(false);
return rv;
}
bool MountVolume(const std::string& device,const std::string& mountPoint,const std::string& fsType,bool bSetReadOnly)
{
int exitCode = 0;
std::string errorMsg = "";
bool bCanMount = false;
bool remount = false;
std::string flags;
if(bSetReadOnly)
flags="ro ";
else
flags="rw ";
std::string sFileSystem = fsType;
if(sFileSystem =="")
sFileSystem ="auto";
std::string sMount = "";
std::string mode;
if ( IsVolumeMounted(device,sMount,mode))
{
if ( sMount == mountPoint)
{
bCanMount = true;
remount = true;
}
}
else
{
bCanMount = true;
}
if ( bCanMount)
{
sFileSystem = ToLower(sFileSystem);
if(!strcmp(sFileSystem.c_str(),"fat32")) {
sFileSystem = "vfat";
}else if(!strcmp(sFileSystem.c_str(),"fat")) {
sFileSystem = "msdos";
}else if(!strcmp(sFileSystem.c_str(),"pcfs")) {
sFileSystem = "vfat";
}
}
bool bmounted = MountDevice(device, mountPoint, fsType, bSetReadOnly, exitCode, errorMsg);
std::string filepath;
bool new_sparsefile_format = false;
bool is_volpack = IsVolPackDevice(device.c_str(),filepath,new_sparsefile_format);
if (bmounted && (!is_volpack))
{
if(!AddFSEntry(device.c_str(),mountPoint.c_str(),sFileSystem.c_str(),flags.c_str(),remount))
{
DebugPrintf(SV_LOG_INFO, "Note: /etc/fstab was not updated. please update it manually.\n");
}
}
return bmounted;
}
/* LINUX SPECIFIC */
bool GetMountPoints(const char * dev, std::vector<std::string> &mountPoints)
{
bool rv = false;
FILE * fp = NULL;
std::string proc_fsname = "";
struct mntent *entry = NULL;
mntent m_Ent;
char m_Buffer[MAXPATHLEN*4];
do
{
memset(&m_Ent, 0, sizeof(m_Ent));
fp = setmntent(SV_PROC_MNTS, "r");
if (fp == NULL)
{
DebugPrintf(SV_LOG_ERROR,
"Function %s @LINE %d in FILE %s :failed to open %s \n",
FUNCTION_NAME, LINE_NO, FILE_NAME, SV_PROC_MNTS);
rv = false;
break;
}
std::string sMountPoint="";
while( (entry = getmntent_r(fp, &m_Ent, m_Buffer, sizeof(m_Buffer))) != NULL )
{
if (!IsValidDevfile(entry->mnt_fsname))
continue;
proc_fsname = entry->mnt_fsname;
GetDeviceNameFromSymLink(proc_fsname);
if ( 0 == strcmp(proc_fsname.c_str(),dev))
mountPoints.push_back(entry->mnt_dir);
}
rv = true;
}while(0);
if ( NULL != fp )
{
endmntent(fp);
}
return rv;
}
/* LINUX SPECIFIC */
SVERROR MakeReadOnly(const char *drive, void *VolumeGUID, etBitOperation ReadOnlyBitFlag)
{
SVERROR sve = SVS_OK;
//Stub for unix
//Always return failure for now
//sve = SVS_FALSE;
int fd;
if ((fd = open(drive, O_RDONLY))< 0)
return SVE_FAIL;
int flag = (ReadOnlyBitFlag == ecBitOpReset)?0:((ReadOnlyBitFlag == ecBitOpSet)?1:0);
bool bResult = false;
bResult = (ioctl(fd, BLKROSET, &flag) == 0); // linux only
close(fd);
if (bResult) {
if(ReadOnlyBitFlag == ecBitOpReset)
DebugPrintf("Reset Read Only Flag on Volume %s: Succeeded\n", drive);
else
DebugPrintf("Set Read Only Flag on Volume %s: Succeeded\n", drive);
} else {
if(ReadOnlyBitFlag == ecBitOpReset)
DebugPrintf(SV_LOG_ERROR, "FAILED to Reset Read Only flag on Volume %s: Failed\n", drive);
else
DebugPrintf(SV_LOG_ERROR, "FAILED to Set Read Only flag on Volume %s: Failed\n", drive);
sve = SVS_FALSE;
}
return sve ;
}
/* LINUX SPECIFIC */
SVERROR isReadOnly(const char * drive, bool & rvalue)
{
SVERROR sve = SVS_OK;
DebugPrintf(SV_LOG_DEBUG, "@ LINE %d in FILE %s, drive = %s\n", LINE_NO, FILE_NAME, drive);
if( NULL == drive )
{
sve = EINVAL;
DebugPrintf( SV_LOG_ERROR, "@ LINE %d in FILE %s \n", __LINE__, __FILE__ );
DebugPrintf( SV_LOG_ERROR, "FAILED UnhideDrive_RW()... err = EINVAL\n");
return sve;
}
std::string sMount = ""; // 3077
std::string mode;
if (!IsVolumeMounted(drive,sMount,mode))
{
DebugPrintf(SV_LOG_DEBUG,"Device %s is not mounted. It means it is hidden .\n",drive);
rvalue=false;
return SVS_FALSE ;
}
int fd;
if ((fd = open(drive, O_RDONLY))< 0)
sve = SVE_FAIL;
int flag;
bool bResult = false;
bResult = (ioctl(fd, BLKROGET, &flag) == 0);
if (bResult)
{
if (flag)
rvalue = true;
else
rvalue = false;
}
else
{
sve = SVS_FALSE;
}
close(fd);
return sve;
}
/* LINUX SPECIFIC */
VOLUME_STATE GetVolumeState(const char * drive)
{
DebugPrintf( SV_LOG_DEBUG, "Entered GetVolumeState\n");
// Algorithm:
// Get actual device name.
// Get all current mount points associated with the device.
// If mount points empty, return HIDDEN
// For each mount point...
// Is it mounted read write, return UNHIDDEN_RW
//
// Return UNHIDDEN_RO
//
bool rv = false;
FILE *fp = NULL;
struct mntent *entry = NULL;
mntent m_Ent;
bool mounted = false;
bool rw = false;
VOLUME_STATE vs = VOLUME_UNKNOWN;
std::string devname = drive;
char m_Buffer[MAXPATHLEN*4];
do
{
memset(&m_Ent, 0, sizeof(m_Ent));
if(!IsVolpackDriverAvailable())
{
std::string sparsefile;
bool new_sparsefile_format = false;
bool is_volpack = IsVolPackDevice(devname.c_str(),sparsefile,new_sparsefile_format);
if(is_volpack)
{
vs = VOLUME_HIDDEN;
break;
}
}
rv = GetDeviceNameFromSymLink(devname);
if(!rv)
{
DebugPrintf(SV_LOG_ERROR, "Function %s @LINE %d in FILE %s :invalid device name %s\n", FUNCTION_NAME, LINE_NO, FILE_NAME,devname.c_str());
vs = VOLUME_UNKNOWN;
break;
}
rv = IsValidDevfile(devname);
if(!rv)
{
DebugPrintf(SV_LOG_ERROR, "Function %s @LINE %d in FILE %s :invalid device name %s\n", FUNCTION_NAME, LINE_NO, FILE_NAME,devname.c_str());
vs = VOLUME_UNKNOWN;
break;
}
fp = setmntent(SV_PROC_MNTS, "r");
if (fp == NULL)
{
DebugPrintf(SV_LOG_ERROR, "Function %s @LINE %d in FILE %s :unable to open %s\n", FUNCTION_NAME, LINE_NO, FILE_NAME,SV_PROC_MNTS);
vs = VOLUME_UNKNOWN;
break;
}
while( (entry = getmntent_r(fp, &m_Ent, m_Buffer, sizeof(m_Buffer))) != NULL )
{
std::string procdevName = entry -> mnt_fsname;
if(!GetDeviceNameFromSymLink(procdevName))
continue;
if (!IsValidDevfile(procdevName))
continue;
if ( procdevName == devname )
{
mounted = true;
if( 0 != strstr(entry->mnt_opts, "rw") )
{
rw = true;
break;
}
}
}
endmntent(fp);
if(mounted)
{
if(rw)
vs = VOLUME_VISIBLE_RW;
else
vs = VOLUME_VISIBLE_RO;
}
else
{
vs = VOLUME_HIDDEN;
}
} while (0);
DebugPrintf( SV_LOG_DEBUG, "Exited GetVolumeState\n");
return vs;
}
/* LINUX SPECIFIC */
bool IsVolumeMounted(const std::string volume,std::string& sMountPoint, std::string &mode)
{
bool bMounted = false;
sMountPoint = "";
if(volume.empty())
{
DebugPrintf(SV_LOG_ERROR,"Null volume name passed.\n");
return false;
}
mntent m_Ent;
char m_Buffer[MAXPATHLEN*4];
memset(&m_Ent, 0, sizeof(m_Ent));
std::string devName = volume;
std::string proc_fsname = "";
GetDeviceNameFromSymLink(devName);
FILE *fp;
struct mntent *entry = NULL;
fp = setmntent(SV_FAST_PROC_MOUNT, "r");
if (fp == NULL)
{
printf("Could not able to open %s \n", setmntent);
return false;
}
while((entry = getmntent_r(fp, &m_Ent, m_Buffer, sizeof(m_Buffer))) && ( false == bMounted))
{
if (!IsValidDevfile(entry->mnt_fsname))
continue;
proc_fsname += entry->mnt_fsname;
GetDeviceNameFromSymLink(proc_fsname);
if ( 0 == strcmp(proc_fsname.c_str(),devName.c_str()))
{
bMounted = true;
sMountPoint+= entry->mnt_dir;
mode=entry->mnt_opts;
}
proc_fsname.clear();
}
if ( NULL != fp )
{
endmntent(fp);
}
return bMounted;
}
/* LINUX SPECIFIC */
/* SHOULD THINK OF MAKING IT COMMAN FOR ALL */
//This function flushes all pending file system buffers (both data and metadata) in a volume. The argument
// should be in the form A: or B: or C: etc
SVERROR FlushFileSystemBuffers(const char *Volume)
{
std::string volName;
ACE_HANDLE hVolume = ACE_INVALID_HANDLE;
SVERROR sve = SVS_OK;
do
{
SV_UINT flags = 0;
volName = Volume;
flags = O_RDWR | O_DIRECT;
hVolume = ACE_OS::open(volName.c_str(), flags, ACE_DEFAULT_OPEN_PERMS);
if(ACE_INVALID_HANDLE == hVolume)
{
sve = ACE_OS::last_error();
DebugPrintf( SV_LOG_ERROR, "@ LINE %d in FILE %s \n", __LINE__, __FILE__ );
DebugPrintf( SV_LOG_ERROR, "ACE_OS::open failed in FlushFileSystemBuffers.We still proceed %s, err = %s\n", volName.c_str(), sve.toString());
break;
}
if (ACE_OS::fsync(hVolume) == -1)
{
sve = ACE_OS::last_error();
DebugPrintf(SV_LOG_WARNING, "FlushFileBuffers for Volume %s did not succeed, err = %s\n", volName.c_str(), sve.toString());
}
else
DebugPrintf(SV_LOG_DEBUG, "FlushFileBuffers for Volume %s Succeeded\n", volName.c_str());
// Flush the buffer cache
if(ioctl(hVolume, BLKFLSBUF,0) == -1)
{
DebugPrintf(SV_LOG_WARNING,
"FlushBufferCache for Volume %s did not succeed\n", volName.c_str());
}
ACE_OS::close(hVolume);
} while (FALSE);
return sve;
}
/* LINUX SPECIFIC */
/* SINCE GetVolSize FUNCTION IS LINUX SPECIFIC */
//-----------------------------------------------------------------------------
// This is a function that works under W2K and later to get the correct volume
// size on all flavors of volumes (static/dynamic, raid/striped/mirror/spanned)
// On WXP and later, IOCTL_DISK_GET_LENGTH_INFO already does this, so that is
// what we try first. This code is a direct translation to user mode of some
// kernel code in host\driver\win32\shared\MntMgr.cpp
//
// IMPORTANT: It turns out from user mode, a file system will slightly reduce
// the size of a volume by hiding some blocks. You need to call the ioctl
// DeviceIoControl(volumeHandle,
// FSCTL_ALLOW_EXTENDED_DASD_IO,
// NULL, 0, NULL, 0, &status, NULL);
// on any volume that uses this function, or expect to read or write ALL of a
// volume. This tells the filesystem to let the underlying volume do the bounds
// checking, not the filesystem This ioctl will probably fail on raw volumes,
// just ignore the error and call it on every volume. You may
// need #define _WIN32_WINNT 0x0510 before your headers to get this ioctl
//
// This function expects as input a handle opened on a volume with at least
// read access. A status value from GetLastErrro() will be return if needed
// The volume size will be in bytes, although always a multiple of 512
//-----------------------------------------------------------------------------
SVERROR GetVolumeSize(ACE_HANDLE volumeHandle,
unsigned long long* volumeSize)
{
SVERROR sve = SVS_OK;
sve = GetVolSize(volumeHandle, volumeSize);
return sve;
}
/* LINUX SPECIFIC */
/* SINCE GetFsVolSize FUNCTION IS LINUX SPECIFIC */
///
/// Returns the total bytes in the volume (not the free space).
/// 0 returned upon failure.
///
SV_LONGLONG GetVolumeCapacity( const char *volume )
{
SV_LONGLONG capacity = 0;
if (GetFsVolSize(volume, (unsigned long long *)&capacity).failed())
capacity = 0;
return( capacity );
}
/* LINUX SPECIFIC */
bool GetVolumeRootPath(const std::string & path, std::string & root)
{
// char rootPath[SV_INTERNET_MAX_PATH_LENGTH];
struct mntent *mntptr;
size_t lenthOfmntdir = 0;
bool found = false;
mntent m_Ent;
char m_Buffer[MAXPATHLEN*4];
memset(&m_Ent, 0, sizeof(m_Ent));
root.clear();
FILE *fp = setmntent(SV_PROC_MNTS,"r");
if(fp == NULL)
return false;
while( (mntptr = getmntent_r(fp, &m_Ent, m_Buffer, sizeof(m_Buffer))) != NULL )
{
lenthOfmntdir = strlen(mntptr->mnt_dir);
if(!strncmp(mntptr->mnt_dir, path.c_str(), lenthOfmntdir)) {
if ( lenthOfmntdir > root.size()) {
root = mntptr->mnt_dir;
found = true;
}
}
}
if(fp)
endmntent(fp);
return found;
}
/* LINUX SPECIFIC */
//
// Function: GetDeviceNameForMountPt
// given a mount point, convert it to corresponding device name
//
bool GetDeviceNameForMountPt(const std::string & mtpt, std::string & devName)
{
bool rv = false;
FILE *fp;
struct mntent *entry = NULL;
mntent m_Ent;
char m_Buffer[MAXPATHLEN*4];
memset(&m_Ent, 0, sizeof(m_Ent));
fp = setmntent(SV_PROC_MNTS, "r");
if (fp == NULL)
{
DebugPrintf(SV_LOG_ERROR, "Could not able to open %s\n", SV_PROC_MNTS);
return false;
}
while( (entry = getmntent_r(fp, &m_Ent, m_Buffer, sizeof(m_Buffer))) != NULL )
{
if (!IsValidDevfile(entry->mnt_fsname))
continue;
if ( 0 == strcmp(entry->mnt_dir, mtpt.c_str()))
{
devName = entry->mnt_fsname;
// convert it to actual device name instead
// of symlink
if(!GetDeviceNameFromSymLink(devName))
continue;
rv = true;
break;
}
}
if ( NULL != fp )
{
endmntent(fp);
}
return rv;
}
/* LINUX SPECIFIC */
bool IsValidMntEnt(mntent *entry)
{
bool valid = true;
if (entry == NULL) valid = false;
if (strcmp(entry->mnt_fsname, "none") == 0) valid = false;
if (strncmp(entry->mnt_dir, "/dev", strlen("/dev")) == 0) valid = false;
if (strcmp(entry->mnt_type, "nfs") == 0) valid = false;
//if (strcmp(entry->mnt_type, "swap") == 0) valid = false;
if (strcmp(entry->mnt_type, "auto") == 0) valid = false; // all removable media
if (strncmp(entry->mnt_dir, "/proc", strlen("/proc")) == 0) valid = false;
return valid;
}
/* LINUX SPECIFIC */
/*
* FUNCTION NAME : mountedVolume
*
* DESCRIPTION : Given a pathname, return the nested volumes beneath it
*
*
* INPUT PARAMETERS : pathname under which nested volumes need to be checked
*
* OUTPUT PARAMETERS : nested volumes
*
* NOTES : doesn't count the provided mountpoint/devicename as a mounted volume
*
* return value : true if nested volumes are found, otherwise false
*
*/
bool mountedvolume( const std::string& pathname, std::string& mountpoints )
{
std::string mntpath = pathname + "/";
FILE* fp = setmntent(SV_PROC_MNTS, "r");
mntent m_Ent;
char m_Buffer[MAXPATHLEN*4];
memset(&m_Ent, 0, sizeof(m_Ent));
if( fp && !pathname.empty() )
{
struct mntent* line;
while( line = getmntent_r(fp, &m_Ent, m_Buffer, sizeof(m_Buffer)) )
{
if( !strncmp( line->mnt_fsname, "/dev/", 5 ) && strcmp( line->mnt_dir, pathname.c_str()))
{
if( !strncmp( line->mnt_dir, mntpath.c_str(), mntpath.size()))
{
mountpoints += line->mnt_dir;
mountpoints += "\n";
}
}
}
}
if(fp)
endmntent(fp);
return mountpoints.empty() ? false : true;
}
/* LINUX SPECIFIC */
int posix_fadvise_wrapper(ACE_HANDLE fd, SV_ULONGLONG offset, SV_ULONGLONG len, int advice)
{
return posix_fadvise(fd, offset, len, advice);
}
/* LINUX SPECIFIC */
void setdirectmode(unsigned long int &access)
{
access |= O_DIRECT;
}
void setdirectmode(int &mode)
{
mode |= O_DIRECT;
}
bool FormVolumeLabel(const std::string device, std::string &label)
{
bool bretval = true;
std::string cmd(SV_LABEL);
cmd += device;
cmd += " 2> /dev/null ";
std::stringstream results;
if (!executePipe(cmd, results))
{
DebugPrintf(SV_LOG_ERROR,
"Function %s @LINE %d in FILE %s :failed to execute cmd %s \n",
FUNCTION_NAME, LINE_NO, FILE_NAME, cmd.c_str());
bretval = false;
}
else
{
std::string e2label = results.str();
trim(e2label);
if (!e2label.empty())
{
label= "LABEL=";
label += e2label;
}
}
return bretval;
}
std::string GetCommandPath(const std::string &cmd)
{
/* APART FROM COMMON PATHS, WE SHOULD FIND AN EQUIVALENT OF "which" COMMAND
* IN THIS CASE, COMMAND SHOULD BE ONLY COMMAND AND SHOULD NOT CONTAIN
* SPACE OR COMMAND OPTIONS
*/
return "/bin:/sbin:/usr/bin:/usr/local/bin";
}
bool GetVolSizeWithOpenflag(const std::string vol, const int oflag, SV_ULONGLONG &refvolsize)
{
DebugPrintf( SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME);
bool bretval = false;
int fd = open(vol.c_str(), oflag);
if (-1 == fd)
{
DebugPrintf( SV_LOG_ERROR, "@ LINE %d in FILE %s, open system call failed for volume %s\n",
__LINE__, __FILE__, vol.c_str());
}
else
{
SV_ULONGLONG vsnapsize = 0;
SV_ULONGLONG sectorsize = 0;
if (ioctl(fd, BLKSSZGET, §orsize) < 0)
{
DebugPrintf(SV_LOG_ERROR, "Failed to obtain the sector size for volume %s\n",
vol.c_str());
}
else
{
if(ioctl(fd, BLKGETSIZE, &vsnapsize) < 0)
{
DebugPrintf(SV_LOG_ERROR, "Failed to obtain the size of volume %s\n", vol.c_str());
}
else
{
refvolsize = vsnapsize * sectorsize;
bretval = true;
}
}
close(fd);
}
DebugPrintf( SV_LOG_DEBUG, "EXITING %s WITH RETURN VALUE %s\n", FUNCTION_NAME, (bretval?"true":"false"));
return bretval;
}
// --------------------------------------------------------------------------
// format volume name the way the CX wants it
// final format should be one of
// <drive>
// <drive>:\[<mntpoint>\]
// where: <drive> is the drive letter and [<mntpoint>\] is optional
// and <mntpoint> is the mount point name
// e.g.
// A:\ for a drive letter
// B:\mnt\data\ for a mount point
// --------------------------------------------------------------------------
void FormatVolumeNameForCxReporting(std::string& volumeName)
{
// we need to strip off any leading \, ., ? if they exists
std::string::size_type idx = volumeName.find_first_not_of("\\.?");
if (std::string::npos != idx) {
volumeName.erase(0, idx);
}
// strip off trailing :\ or : if they exist
std::string::size_type len = volumeName.length();
idx = len;
if ('\\' == volumeName[len - 1] || ':' == volumeName[len - 1]) {
--idx;
}
if (':' == volumeName[len - 2])
{
--idx;
}
if (idx < len) {
volumeName.erase(idx);
}
}
bool GetSectorSizeWithFd(int fd, const std::string vol, SV_ULONG &SectorSize)
{
bool bretval = false;
if (-1 == fd)
{
DebugPrintf(SV_LOG_ERROR, "@ LINE %d in FILE %s, invalid fd = %d\n", LINE_NO, FILE_NAME, fd);
}
else
{
SV_ULONG volsectorsize = 0;
if (ioctl(fd, BLKSSZGET, &volsectorsize) < 0)
{
DebugPrintf(SV_LOG_ERROR, "@ LINE %d in FILE %s, failed to get sector size for volume %s\n", LINE_NO, FILE_NAME, vol.c_str());
}
else
{
SectorSize = volsectorsize;
bretval = true;
}
}
return bretval;
}
bool GetNumBlocksWithFd(int fd, const std::string vol, SV_ULONGLONG &NumBlks)
{
bool bretval = false;
if (-1 == fd)
{
DebugPrintf(SV_LOG_ERROR, "@ LINE %d in FILE %s, invalid fd = %d\n", LINE_NO, FILE_NAME, fd);
}
else
{
SV_ULONGLONG volnumblks = 0;
if (ioctl(fd, BLKGETSIZE, &volnumblks) < 0)
{
DebugPrintf(SV_LOG_ERROR, "@ LINE %d in FILE %s, failed to get number of blocks for volume %s\n", LINE_NO, FILE_NAME, vol.c_str());
}
else
{
NumBlks = volnumblks;
bretval = true;
}
}
return bretval;
}
/* LINUX SPECIFIC */
/* The reason is that in linux, the device name
* is although a link to the real name, read link
* on device name gives absolute path of the real name
* but in solaris, readlink on device name gives the
* relative path. This function can be made common
* to unix once the solaris version(which should work
* for both solaris and linux) is tested on linux)
*/
//
// Gets the root device name from a symbolic link
//
bool GetDeviceNameFromSymLink(std::string &deviceName)
{
if (NULL == deviceName.c_str()) {
return false;
}
if(deviceName.compare(0,11,"/dev/mapper") == 0)
{
return true;
}
std::string linkName = deviceName;
// make sure device is valid
struct stat64 volStat;
// make sure device file exists
if (-1 == lstat64(deviceName.c_str(), &volStat)) {
return false;
}
const char UNIXROOTDIR = '/';
const char UNIXDIRSEPARATOR = '/';
if (S_ISLNK(volStat.st_mode)) {
ssize_t len;
char symlnk[255]; // note should be max path not 255
do {
len = readlink(deviceName.c_str(), symlnk, sizeof(symlnk) - 1);
if (-1 == len) {
break;
}
symlnk[len] = '\0';
if (UNIXROOTDIR != symlnk[0])
{
std::string catenatedlinkname = dirname_r(deviceName.c_str());
catenatedlinkname += UNIXDIRSEPARATOR;
catenatedlinkname += symlnk;
char absolutename[PATH_MAX + 1] = {'\0'};
if (NULL == realpath(catenatedlinkname.c_str(), absolutename))
{
DebugPrintf(SV_LOG_ERROR,"realpath failed @ LINE %d in FILE %s for file %s with errno = %d.\n", LINE_NO, FILE_NAME,
deviceName.c_str(), errno);
break;
}
deviceName = absolutename;
}
else
deviceName = symlnk;
} while (true);
if (-1 == lstat64(deviceName.c_str(), &volStat)) {
DebugPrintf(SV_LOG_WARNING,"Unable to determine attributes of file %s \n",linkName.c_str());
return false;
}
}
return true;
}
bool IsReportingRealNameToCx(void)
{
return true;
}
bool GetLinkNameIfRealDeviceName(const std::string sVolName, std::string &sLinkName)
{
sLinkName = sVolName;
return true;
}
std::string GetRawVolumeName(const std::string &dskname)
{
return dskname;
}
/* LINUX */
bool IsProcessRunning(const std::string &sProcessName, uint32_t numExpectedInstances)
{
const char *procdir = "/proc"; /* standard /proc directory */
bool rv = false;
DIR *dirp;
int pdlen;
char psname[100];
char buffer[1024];
char filename[100];
struct dirent *dentp;
int cnt = 0;
const std::string self = "self";
const std::string thread_self = "thread-self";
do
{
if ((dirp = opendir(procdir)) == NULL)
{
printf("Failed Opening proc directory \n");
rv = false;
break;
}
(void) inm_strcpy_s(psname, ARRAYSIZE(psname), procdir);
pdlen = strlen(psname);
psname[pdlen++] = '/';
while (dentp = readdir(dirp))
{
int psfd; /* file descriptor for /proc/nnnnn/stat */
if (dentp->d_name[0] == '.') /* skip . and .. */
continue;
if (!strcmp(self.c_str(), dentp->d_name) ||
!strcmp(thread_self.c_str(), dentp->d_name))
{
continue;
}
(void) inm_strcpy_s(psname + pdlen, ARRAYSIZE(psname) - pdlen, dentp->d_name);
(void) inm_strcat_s(psname, ARRAYSIZE(psname), "/stat");
if ((psfd = open(psname, O_RDONLY)) == -1)
continue;
int bytes = read(psfd,buffer,1024);
close(psfd);
if( bytes > 0)
{
int i=0,j=0;
while(buffer[i] != '(')
i++;
i++;
for(;buffer[i]!= ')'; i++,j++)
{
filename[j]=buffer[i];
}
filename[j] = '\0';
std::string check = filename;
if(!strcmp(sProcessName.c_str(),check.c_str()))
{
cnt++;
DebugPrintf(SV_LOG_DEBUG, "Name: %s PID: %s\n", check.c_str(), dentp->d_name);
if (cnt > numExpectedInstances)
{
rv = true;
break;
}
}
}
}
closedir(dirp);
}while(0);
return rv;
}
bool isLocalMachine32Bit( std::string machine)
{
DebugPrintf( SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME);
std::string uname_machine = machine;
DebugPrintf( SV_LOG_DEBUG, "Machine Vaue %s\n", machine.c_str() );
removeStringSpaces( uname_machine );
bool bis32BitMachine = false;
int i = 0;
for( ;i < 10;i++ )
{
std::stringstream sub;
sub<< "i" << i << "86";
if( uname_machine.find( sub.str() ) != std::string::npos )
{
bis32BitMachine = true;
break;
}
}
DebugPrintf( SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME);
return bis32BitMachine;
}
SVERROR getLinuxReleaseValue( std::string & linuxetcReleaseValue, LINUX_TYPE& linuxFlavourType )
{
DebugPrintf( SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME);
SVERROR bRet = SVS_OK;
std::string redhat_release_Value, SuSE_release_Value, debian_release_Value, ubuntu_release_Value, enterprise_release_Value, oracle_release_Value, release_Value;
if( getFileContent( "/etc/enterprise-release", enterprise_release_Value ) == SVS_OK )
{
linuxetcReleaseValue = enterprise_release_Value;
linuxFlavourType = OEL5_RELEASE;
}
else if( getFileContent( "/etc/oracle-release", oracle_release_Value ) == SVS_OK )
{
linuxetcReleaseValue = oracle_release_Value;
linuxFlavourType = OEL_RELEASE;
}
else if( getFileContent( "/etc/redhat-release", redhat_release_Value ) == SVS_OK )
{
linuxetcReleaseValue = redhat_release_Value;
linuxFlavourType = REDHAT_RELEASE;
}
else if( getFileContent( "/etc/SuSE-release", SuSE_release_Value ) == SVS_OK && (SuSE_release_Value.find("VERSION = 12") != std::string::npos || SuSE_release_Value.find("VERSION = 11") != std::string::npos))
{
linuxetcReleaseValue = SuSE_release_Value;
linuxFlavourType = SUSE_RELEASE;
}
else if( getFileContent( "/etc/lsb-release", ubuntu_release_Value ) == SVS_OK )
{
linuxetcReleaseValue = ubuntu_release_Value;
linuxFlavourType = UBUNTU_RELEASE;
}
else if( getFileContent( "/etc/os-release", release_Value ) == SVS_OK )
{
linuxetcReleaseValue = release_Value;
if( release_Value.find("SLES") == std::string::npos )
{
linuxFlavourType = DEBAIN_RELEASE;
}
else
{
linuxFlavourType = SUSE_RELEASE;
}
}
else
{
bRet = SVS_FALSE;
}
return bRet;
DebugPrintf( SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME);
}
bool IsOpenVzVM(Pats &pats, std::string &hypervisorname, std::string &hypervisorvers)
{
bool bisvm = false;
DIR *dirp;
dirp = opendir(OPENVZVMVZDIR);
if (dirp)
{
closedir(dirp);
dirp = opendir(OPENVZVMBCDIR);
if (dirp)
{
closedir(dirp);
}
else
{
hypervisorname = HYPERVISOROPENVZ;
bisvm = true;
}
}
return bisvm;
}
bool IsVMFromCpuInfo(Pats &pats, std::string &hypervisorname, std::string &hypervisorvers)
{
bool bisvm = false;
std::vector<std::string> vmpatsincpuinfo;
vmpatsincpuinfo.push_back(QEMUPAT);
vmpatsincpuinfo.push_back(UMLPAT);
Pats vmcpuinfopats(vmpatsincpuinfo);
std::ifstream cpuinfostream(CPUINFOFILE);
if (cpuinfostream.is_open())
{
while (!cpuinfostream.eof())
{
std::string line;
std::getline(cpuinfostream, line);
if (line.empty())
{
break;
}
bisvm = vmcpuinfopats.IsMatched(line, hypervisorname);
if (bisvm)
{
break;
}
}
cpuinfostream.close();
}
return bisvm;
}
bool IsNativeVm(Pats &pats, std::string &hypervisorname, std::string &hypervisorvers)
{
return false;
}
bool IsXenVm(Pats &pats, std::string &hypervisorname, std::string &hypervisorvers)
{
std::string output, err;
int ecode = 0;
bool bisxen = RunInmCommand(ISXENCMD, output, err, ecode);
if (bisxen)
{
hypervisorname = XENNAME;
}
return bisxen;
}
bool HasNicInfoPhysicaIPs(const NicInfos_t &nicinfos)
{
// dummy function
return true;
}
void GetNicInfos(NicInfos_t & nicInfos)
{
int sockfd = -1;
bool bgotnicinfos = true;
DebugPrintf( SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME);
sockfd = socket(PF_INET, SOCK_DGRAM, 0);
if (-1 != sockfd)
{
struct ifconf ifc;
int inifclen;
void *pv = NULL;
void *pvsby = NULL;
int ioctlrval = -1;
size_t sizeofifreq = sizeof (struct ifreq);
size_t initsize;
INM_SAFE_ARITHMETIC(initsize = ((TYPICAL_NADAPTERS - 1) * InmSafeInt<size_t>::Type(sizeofifreq)), INMAGE_EX(sizeofifreq))
inifclen = initsize;
ifc.ifc_req = NULL;
do
{
INM_SAFE_ARITHMETIC(inifclen += InmSafeInt<size_t>::Type(sizeofifreq), INMAGE_EX(inifclen)(sizeofifreq))
ifc.ifc_len = inifclen;
pvsby = realloc(pv, ifc.ifc_len);
if (pvsby)
{
pv = pvsby;
ifc.ifc_req = (struct ifreq *)pv;
ioctlrval = ioctl(sockfd, SIOCGIFCONF, &ifc);
if (ioctlrval)
{
DebugPrintf(SV_LOG_ERROR, "ioctl SIOCGIFCONF failed with errno = %d\n", errno);
bgotnicinfos = false;
break;
}
}
else
{
DebugPrintf(SV_LOG_ERROR, "realloc to allocate memory for network interfaces failed with errno = %d\n", errno);
bgotnicinfos = false;
break;
}
} while(inifclen <= ifc.ifc_len);
if (bgotnicinfos)
{
bgotnicinfos = FillNicInfos(sockfd, &ifc, sizeofifreq, nicInfos);
}
if (pv)
{
free(pv);
}
close(sockfd);
}
else
{
DebugPrintf(SV_LOG_ERROR, "socket call failed with errno = %d\n", errno);
bgotnicinfos = false;
}
if (bgotnicinfos)
{
std::string gws = GetDefaultGateways(NSNicInfo::DELIM);
DebugPrintf(SV_LOG_DEBUG, "gateways = %s\n", gws.c_str());
if (!gws.empty())
{
UpdateNicInfoAttr(NSNicInfo::DEFAULT_IP_GATEWAYS, gws, nicInfos);
}
std::string nameservers = GetNameServerAddresses(NSNicInfo::DELIM);
DebugPrintf(SV_LOG_DEBUG, "nameserver ip addresses = %s\n", nameservers.c_str());
if (!nameservers.empty())
{
UpdateNicInfoAttr(NSNicInfo::DNS_SERVER_ADDRESSES, nameservers, nicInfos);
}
}
else
{
DebugPrintf(SV_LOG_ERROR, "cannot collect the network interfaces information\n");
}
DebugPrintf( SV_LOG_DEBUG, "EXITING %s\n", FUNCTION_NAME);
}
bool FillNicInfos(const int &sockfd, struct ifconf *pifc, size_t sizeofifreq, NicInfos_t & nicInfos)
{
DebugPrintf( SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME);
bool bfillnicinfos = true;
int numifreq = (pifc->ifc_len / sizeofifreq);
char ipaddr[INET_ADDRSTRLEN] = "\0";
const char *prval = NULL;
struct sockaddr_in *sa = NULL;
bool bcollect;
std::set<std::string> ifsfromifconf;
std::string DHCPValue;
E_INM_TRISTATE e;
for (int i = 0; i < numifreq; i++)
{
ifsfromifconf.insert(pifc->ifc_req[i].ifr_name);
sa = (struct sockaddr_in *)&(pifc->ifc_req[i].ifr_addr);
prval = inet_ntop(AF_INET, &(sa->sin_addr.s_addr), ipaddr, sizeof ipaddr);
if (prval)
{
bcollect = ShouldCollectNicInfo(sockfd, pifc->ifc_req + i, ipaddr);
if (bcollect)
{
std::string hardwareaddress;
std::string netmask;
GetNetIfParameters(pifc->ifc_req[i].ifr_name, hardwareaddress, netmask);
if (hardwareaddress.empty())
{
continue;
}
e = getDHCPValue(pifc->ifc_req[i].ifr_name,DHCPValue ) ? E_INM_TRISTATE_TRUE : E_INM_TRISTATE_FALSE;
InsertNicInfo(nicInfos, pifc->ifc_req[i].ifr_name, hardwareaddress, ipaddr, netmask, e);
}
else
{
DebugPrintf(SV_LOG_DEBUG, "Not collecting information for nic %s\n", pifc->ifc_req[i].ifr_name);
}
}
else
{
DebugPrintf(SV_LOG_ERROR, "converting network ip address for interface %s to"
" readble string failed with errno = %d."
" processing next interface if available\n",
pifc->ifc_req[i].ifr_name, errno);
}
} /* for */
std::set<std::string> ifsfromproc;
GetNicNamesFromProc(ifsfromproc);
std::vector<std::string> ifsleftinproc(ifsfromproc.size());
std::vector<std::string>::iterator endit = std::set_difference(ifsfromproc.begin(), ifsfromproc.end(),
ifsfromifconf.begin(), ifsfromifconf.end(),
ifsleftinproc.begin());
for (std::vector<std::string>::const_iterator it = ifsleftinproc.begin(); it != endit; it++)
{
const std::string &ifname = *it;
DebugPrintf(SV_LOG_DEBUG, "interface %s is got from proc\n", ifname.c_str());
std::string hardwareaddress;
std::string netmask;
GetNetIfParameters(ifname, hardwareaddress, netmask);
if (hardwareaddress.empty())
{
continue;
}
e = getDHCPValue(ifname,DHCPValue ) ? E_INM_TRISTATE_TRUE : E_INM_TRISTATE_FALSE;
InsertNicInfo(nicInfos, ifname, hardwareaddress, std::string(), netmask, e);
}
DebugPrintf( SV_LOG_DEBUG, "EXITING %s\n", FUNCTION_NAME);
return bfillnicinfos;
}
void GetNicNamesFromProc(std::set<std::string> &nicnamesfromproc)
{
const std::string PROC_NET_DEV_FILE = "/proc/net/dev";
std::ifstream fs(PROC_NET_DEV_FILE.c_str());
if (fs.is_open())
{
/* skip the two lines at start
[root@TST-BLD-CENTOS5U5-64-10 host]# cat /proc/net/dev
* Inter-| Receive | Transmit
* face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
* lo: 199889 1374 0 0 0 0 0 0 199889 1374 0 0 0 0 0 0
* eth0:18016576209 229921346 0 0 0 0 0 0 11744040036 9463118 0 0 0 0 0 0
* sit0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
*/
const char NICNAMESEP = ':';
std::string line;
std::getline(fs, line);
std::getline(fs, line);
while (!fs.eof())
{
line.clear();
std::getline(fs, line);
if (line.empty())
{
break;
}
std::stringstream ss(line);
std::string in;
ss >> in;
if (!in.empty())
{
size_t colonpos = in.find_first_of(NICNAMESEP);
if (std::string::npos != colonpos)
{
in.erase(colonpos);
nicnamesfromproc.insert(in);
}
}
}
fs.close();
}
}
bool ShouldCollectNicInfo(const int &sockfd, struct ifreq *pifr, const char *ipaddr)
{
bool bshouldcollect = false;
int ioctlrval = -1;
DebugPrintf( SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME);
ioctlrval = ioctl(sockfd, SIOCGIFFLAGS, pifr);
if (!ioctlrval)
{
if (pifr->ifr_flags & IFF_UP)
{
bshouldcollect = !(pifr->ifr_flags & IFF_LOOPBACK);
}
}
else
{
DebugPrintf(SV_LOG_ERROR, "ioctl SIOCGIFFLAGS failed on interface %s."
" However trying to report IP and Interface name\n", pifr->ifr_name);
bshouldcollect = true;
}
if (bshouldcollect)
{
bshouldcollect = IsValidIP(ipaddr);
}
DebugPrintf( SV_LOG_DEBUG, "EXITING %s\n", FUNCTION_NAME);
return bshouldcollect;
}
SV_ULONGLONG GetTotalFileSystemSpace(const struct statvfs64 &vfs)
{
SV_ULONGLONG space = ((SV_ULONGLONG)vfs.f_blocks) * ((SV_ULONGLONG)vfs.f_bsize);
return space;
}
SV_ULONGLONG GetFreeFileSystemSpace(const struct statvfs64 &vfs)
{
SV_ULONGLONG space = ((SV_ULONGLONG)vfs.f_bavail) * ((SV_ULONGLONG)vfs.f_bsize);
return space;
}
void GetNetIfParameters(const std::string &ifrName, std::string& hardwareAddress, std::string &netmask)
{
int fd = socket(AF_INET, SOCK_DGRAM, 0);
if (-1 == fd)
{
DebugPrintf(SV_LOG_DEBUG, "For getting hardware address for network interface %s, "
"creating socked failed with error %s\n", ifrName.c_str(),
strerror(errno));
return;
}
struct ifreq ifr;
ifr.ifr_addr.sa_family = AF_INET;
inm_strncpy_s(ifr.ifr_name, ARRAYSIZE(ifr.ifr_name), ifrName.c_str(), IFNAMSIZ-1);
if (0 == ioctl(fd, SIOCGIFHWADDR, &ifr))
{
if ((unsigned char)ifr.ifr_hwaddr.sa_data[0] ||
(unsigned char)ifr.ifr_hwaddr.sa_data[1] ||
(unsigned char)ifr.ifr_hwaddr.sa_data[2] ||
(unsigned char)ifr.ifr_hwaddr.sa_data[3] ||
(unsigned char)ifr.ifr_hwaddr.sa_data[4] ||
(unsigned char)ifr.ifr_hwaddr.sa_data[5])
{
char HwAddr[256] ;
inm_sprintf_s(HwAddr, ARRAYSIZE(HwAddr), "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n",
(unsigned char)ifr.ifr_hwaddr.sa_data[0],
(unsigned char)ifr.ifr_hwaddr.sa_data[1],
(unsigned char)ifr.ifr_hwaddr.sa_data[2],
(unsigned char)ifr.ifr_hwaddr.sa_data[3],
(unsigned char)ifr.ifr_hwaddr.sa_data[4],
(unsigned char)ifr.ifr_hwaddr.sa_data[5]);
hardwareAddress = HwAddr ;
DebugPrintf(SV_LOG_DEBUG, "Interface Name %s Hardware Address %s\n", ifrName.c_str(), hardwareAddress.c_str()) ;
}
else
{
DebugPrintf(SV_LOG_DEBUG, "For interface Name %s, hardware address is NULL. Hence not reporting\n", ifrName.c_str());
}
}
else
{
DebugPrintf(SV_LOG_DEBUG, "For getting hardware address for network interface %s, "
"ioctl SIOCGIFHWADDR failed with error: %s\n", ifrName.c_str(),
strerror(errno));
}
if (!hardwareAddress.empty())
{
if (0 == ioctl(fd, SIOCGIFNETMASK, &ifr))
{
char mask[INET_ADDRSTRLEN] = "\0";
struct sockaddr_in *sa = (struct sockaddr_in *)&(ifr.ifr_netmask);
const char *prval = inet_ntop(AF_INET, &(sa->sin_addr.s_addr), mask, sizeof mask);
netmask = mask;
DebugPrintf(SV_LOG_DEBUG, "Interface Name %s subnet mask %s\n", ifrName.c_str(), mask);
}
else
{
DebugPrintf(SV_LOG_DEBUG, "For getting netmask for network interface %s, "
"ioctl SIOCGIFNETMASK failed with error: %s\n", ifrName.c_str(),
strerror(errno));
}
}
close(fd);
}
std::string GetExecdName(void)
{
std::string procName;
pid_t parent = ACE_OS::getpid();
std::stringstream proccessfile;
proccessfile << "/proc/" << parent << "/cmdline";
std::ifstream procfile(proccessfile.str().c_str());
procfile >> procName;
procfile.close();
return procName;
}
bool RemoveVgWithAllLvsForVsnap(const std::string & device,std::string& output, std::string& error,bool needvgcleanup)
{
return true;
}
bool getDHCPValue( std::string interface, std::string& value )
{
std::string fileName;
std::string line;
std::istringstream sin;
fileName = "/etc/sysconfig/network-scripts/ifcfg-" + interface;
std::ifstream fin(fileName.c_str());
if(fin.good())
{
while (std::getline(fin, line))
{
sin.str(line.substr(line.find("=")+1));
if (line.find("BOOTPROTO") != std::string::npos)
{
sin >> value;
if(value.find("dhcp") != std::string::npos)
return true;
else
return false;
}
sin.clear();
}
}
else
{
DebugPrintf(SV_LOG_DEBUG, "Unable to open file = %s.\n",fileName.c_str());
return false;
}
return false;
}