in src/common/commonutils/MountUtils.c [199:450]
int SetFileSystemMountingOption(const char* mountDirectory, const char* mountType, const char* desiredOption, OsConfigLogHandle log)
{
const char* fsMountTable = "/etc/fstab";
const char* mountTable = "/etc/mtab";
const char tempFileNameTemplate[] = "/etc/~xtab%d";
const char* newLineAsIsTemplate = "\n%s %s %s %s %d %d";
const char* newLineAddNewTemplate = "\n%s %s %s %s,%s %d %d";
const char* mountAll = "mount -a";
FILE* fsMountHandle = NULL;
FILE* mountHandle = NULL;
char* newLine = NULL;
char* tempFileNameOne = NULL;
char* tempFileNameTwo = NULL;
char* tempFileNameThree = NULL;
struct mntent* mountStruct = NULL;
bool matchFound = false;
int lineNumber = 1;
int status = 0;
if (((NULL == mountDirectory) && (NULL == mountType)) || (NULL == desiredOption))
{
OsConfigLogError(log, "SetFileSystemMountingOption called with invalid argument(s)");
return EINVAL;
}
if (!FileExists(fsMountTable))
{
OsConfigLogInfo(log, "SetFileSystemMountingOption: '%s' not found, no place to set mounting options", fsMountTable);
return 0;
}
if ((NULL == (tempFileNameOne = FormatAllocateString(tempFileNameTemplate, 1))) ||
(NULL == (tempFileNameTwo = FormatAllocateString(tempFileNameTemplate, 2))) ||
(NULL == (tempFileNameThree = FormatAllocateString(tempFileNameTemplate, 3))))
{
OsConfigLogError(log, "SetFileSystemMountingOption: out of memory");
status = ENOMEM;
}
if (0 == status)
{
if (NULL != (fsMountHandle = setmntent(fsMountTable, "r")))
{
OsConfigLogInfo(log, "SetFileSystemMountingOption: looking for entries with mount directory '%s' or mount type '%s' in '%s'",
mountDirectory ? mountDirectory : "-", mountType ? mountType : "-", fsMountTable);
while (NULL != (mountStruct = getmntent(fsMountHandle)))
{
if (((NULL != mountDirectory) && (NULL != mountStruct->mnt_dir) && (NULL != strstr(mountStruct->mnt_dir, mountDirectory))) ||
((NULL != mountType) && (NULL != mountStruct->mnt_type) && (NULL != strstr(mountStruct->mnt_type, mountType))))
{
matchFound = true;
if (NULL != hasmntopt(mountStruct, desiredOption))
{
OsConfigLogInfo(log, "SetFileSystemMountingOption: option '%s' for mount directory '%s' or mount type '%s' already set in '%s' at line %d ('%s')",
desiredOption, mountDirectory ? mountDirectory : "-", mountType ? mountType : "-", fsMountTable, lineNumber, mountStruct->mnt_opts);
// The option is found, copy this mount entry as-is
FREE_MEMORY(newLine);
newLine = FormatAllocateString(newLineAsIsTemplate, mountStruct->mnt_fsname, mountStruct->mnt_dir, mountStruct->mnt_type,
mountStruct->mnt_opts, mountStruct->mnt_freq, mountStruct->mnt_passno);
}
else
{
OsConfigLogInfo(log, "SetFileSystemMountingOption: option '%s' for mount directory '%s' or mount type '%s' missing from file '%s' at line %d ('%s')",
desiredOption, mountDirectory ? mountDirectory : "-", mountType ? mountType : "-", fsMountTable, lineNumber, mountStruct->mnt_opts);
// The option is not found and is needed for this entry, add the needed option when copying this mount entry
FREE_MEMORY(newLine);
newLine = FormatAllocateString(newLineAddNewTemplate, mountStruct->mnt_fsname, mountStruct->mnt_dir, mountStruct->mnt_type,
mountStruct->mnt_opts, desiredOption, mountStruct->mnt_freq, mountStruct->mnt_passno);
}
if (NULL != newLine)
{
if (0 != LineAlreadyExistsInFile(tempFileNameOne, newLine, log))
{
if (0 != (status = AppendPayloadToFile(tempFileNameOne, newLine, (const int)strlen(newLine), log) ? 0 : ENOENT))
{
OsConfigLogInfo(log, "SetFileSystemMountingOption: cannot collect entries from '%s'", fsMountTable);
break;
}
}
}
else
{
OsConfigLogError(log, "SetFileSystemMountingOption: out of memory");
status = ENOMEM;
break;
}
}
else
{
// No match for this mount entry, copy the entire entry as-is
FREE_MEMORY(newLine);
if (NULL != (newLine = FormatAllocateString(newLineAsIsTemplate, mountStruct->mnt_fsname, mountStruct->mnt_dir, mountStruct->mnt_type,
mountStruct->mnt_opts, mountStruct->mnt_freq, mountStruct->mnt_passno)))
{
if (0 != LineAlreadyExistsInFile(tempFileNameOne, newLine, log))
{
if (0 != (status = AppendPayloadToFile(tempFileNameOne, newLine, (const int)strlen(newLine), log) ? 0 : ENOENT))
{
OsConfigLogInfo(log, "SetFileSystemMountingOption: cannot copy existing entries from '%s'", fsMountTable);
break;
}
}
}
else
{
OsConfigLogError(log, "SetFileSystemMountingOption: out of memory");
status = ENOMEM;
break;
}
}
lineNumber += 1;
}
endmntent(fsMountHandle);
if (false == matchFound)
{
OsConfigLogInfo(log, "SetFileSystemMountingOption: mount directory '%s' and/or mount type '%s' not found in '%s'",
mountDirectory ? mountDirectory : "-", mountType ? mountType : "-", fsMountTable);
// No relevant mount entries found in /etc/fstab, try to find and copy entries from /etc/mtab if there are any matching
if (FileExists(mountTable))
{
if (NULL != (mountHandle = setmntent(mountTable, "r")))
{
lineNumber = 1;
OsConfigLogInfo(log, "SetFileSystemMountingOption: looking for entries with mount directory '%s' or mount type '%s' in '%s'",
mountDirectory ? mountDirectory : "-", mountType ? mountType : "-", mountTable);
while (NULL != (mountStruct = getmntent(mountHandle)))
{
if (((NULL != mountDirectory) && (NULL != mountStruct->mnt_dir) && (NULL != strstr(mountStruct->mnt_dir, mountDirectory))) ||
((NULL != mountType) && (NULL != mountStruct->mnt_type) && (NULL != strstr(mountStruct->mnt_type, mountType))))
{
matchFound = true;
if (NULL != hasmntopt(mountStruct, desiredOption))
{
OsConfigLogInfo(log, "SetFileSystemMountingOption: option '%s' for mount directory '%s' or mount type '%s' found set in '%s' at line %d ('%s')",
desiredOption, mountDirectory ? mountDirectory : "-", mountType ? mountType : "-", mountTable, lineNumber, mountStruct->mnt_opts);
// Copy this mount entry as-is
FREE_MEMORY(newLine);
newLine = FormatAllocateString(newLineAsIsTemplate, mountStruct->mnt_fsname, mountStruct->mnt_dir, mountStruct->mnt_type,
mountStruct->mnt_opts, mountStruct->mnt_freq, mountStruct->mnt_passno);
}
else
{
OsConfigLogInfo(log, "SetFileSystemMountingOption: option '%s' for mount directory '%s' or mount type '%s' found missing from '%s' at line %d ('%s')",
desiredOption, mountDirectory ? mountDirectory : "-", mountType ? mountType : "-", mountTable, lineNumber, mountStruct->mnt_opts);
// The option is not found and is needed for this entry, add it when copying this entry
FREE_MEMORY(newLine);
newLine = FormatAllocateString(newLineAddNewTemplate, mountStruct->mnt_fsname, mountStruct->mnt_dir, mountStruct->mnt_type,
mountStruct->mnt_opts, desiredOption, mountStruct->mnt_freq, mountStruct->mnt_passno);
}
if (NULL != newLine)
{
if (0 != LineAlreadyExistsInFile(tempFileNameOne, newLine, log))
{
if (0 != (status = AppendPayloadToFile(tempFileNameOne, newLine, (const int)strlen(newLine), log) ? 0 : ENOENT))
{
OsConfigLogInfo(log, "SetFileSystemMountingOption: cannot collect entry from '%s'", mountTable);
break;
}
}
}
else
{
OsConfigLogError(log, "SetFileSystemMountingOption: out of memory");
status = ENOMEM;
break;
}
}
lineNumber += 1;
}
endmntent(mountHandle);
}
else
{
status = (0 == errno) ? ENOENT : errno;
OsConfigLogInfo(log, "SetFileSystemMountingOption: cannot open '%s', setmntent() failed (%d)", mountTable, status);
}
}
}
if (false == matchFound)
{
OsConfigLogInfo(log, "SetFileSystemMountingOption: mount directory '%s' and/or mount type '%s' not found in either '%s' or '%s', nothing to remediate",
mountDirectory ? mountDirectory : "-", mountType ? mountType : "-", fsMountTable, mountTable);
}
}
else
{
status = (0 == errno) ? ENOENT : errno;
OsConfigLogInfo(log, "SetFileSystemMountingOption: cannot open '%s', setmntent() failed (%d)", fsMountTable, status);
}
if (matchFound && (0 == status))
{
// Copy from the manually built temp mount file one to the temp mount file two using the *mntent API to ensure correct format
if (0 == (status = CopyMountTableFile(tempFileNameOne, tempFileNameTwo, log)))
{
// Optionally, try to preserve the commented out lines from original /etc/fstab
if (MakeFileBackupCopy(fsMountTable, tempFileNameThree, false, log))
{
// Skip all lines containing either paths or 'UUID' entries
if ((0 == ReplaceMarkedLinesInFile(tempFileNameThree, "/", NULL, '#', false, log)) &&
(0 == ReplaceMarkedLinesInFile(tempFileNameThree, "UUID", NULL, '#', false, log)))
{
if (ConcatenateFiles(tempFileNameThree, tempFileNameTwo, false, log))
{
RenameFile(tempFileNameThree, tempFileNameTwo, log);
}
}
}
// When done assembling the final temp mount file two, move it in an atomic step to real mount file
if (0 == (status = RenameFileWithOwnerAndAccess(tempFileNameTwo, fsMountTable, log)))
{
// Command may fail when one configured mount point is not present, so ignore failures
ExecuteCommand(NULL, mountAll, false, false, 0, 0, NULL, NULL, NULL);
}
else
{
OsConfigLogInfo(log, "SetFileSystemMountingOption: RenameFileWithOwnerAndAccess('%s' to '%s') returned %d", tempFileNameTwo, fsMountTable, status);
}
}
}
remove(tempFileNameOne);
remove(tempFileNameTwo);
remove(tempFileNameThree);
}
FREE_MEMORY(newLine);
FREE_MEMORY(tempFileNameOne);
FREE_MEMORY(tempFileNameTwo);
FREE_MEMORY(tempFileNameThree);
return status;
}