542 lines
9.5 KiB
C++
542 lines
9.5 KiB
C++
/*
|
|
* This file is a part of Winix
|
|
* and is distributed under the 2-Clause BSD licence.
|
|
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
|
*/
|
|
|
|
/*
|
|
* Copyright (c) 2010-2022, Tomasz Sowa
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright notice,
|
|
* this list of conditions and the following disclaimer.
|
|
*
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
*/
|
|
|
|
#include "mountparser.h"
|
|
#include "log.h"
|
|
#include "misc.h"
|
|
#include "dirs.h"
|
|
|
|
|
|
namespace Winix
|
|
{
|
|
|
|
|
|
|
|
MountParser::MountParser()
|
|
{
|
|
dirs = 0;
|
|
skip_static = false;
|
|
mount_type_tab = 0;
|
|
mount_fs_tab = 0;
|
|
mount_par_tab = 0;
|
|
static_mount_id = -1;
|
|
}
|
|
|
|
|
|
|
|
void MountParser::SkipStaticDirs(bool skip)
|
|
{
|
|
skip_static = skip;
|
|
}
|
|
|
|
|
|
void MountParser::SetStaticMountId(int id)
|
|
{
|
|
static_mount_id = id;
|
|
}
|
|
|
|
|
|
void MountParser::SetDirs(Dirs * pdirs)
|
|
{
|
|
dirs = pdirs;
|
|
}
|
|
|
|
|
|
void MountParser::SetMountTypeTab(const std::vector<std::wstring> & tab)
|
|
{
|
|
mount_type_tab = &tab;
|
|
}
|
|
|
|
|
|
void MountParser::SetMountFsTab(const std::vector<std::wstring> & tab)
|
|
{
|
|
mount_fs_tab = &tab;
|
|
}
|
|
|
|
|
|
void MountParser::SetMountParTab(const std::vector<std::wstring> & tab)
|
|
{
|
|
mount_par_tab = &tab;
|
|
}
|
|
|
|
|
|
|
|
bool MountParser::IsWhite(int c)
|
|
{
|
|
if( c==' ' || c=='\t' || c==13 || c==160 )
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
void MountParser::SkipWhite()
|
|
{
|
|
while( IsWhite(*pinput) )
|
|
++pinput;
|
|
}
|
|
|
|
|
|
void MountParser::SkipLine()
|
|
{
|
|
while( *pinput && *pinput != 10 )
|
|
++pinput;
|
|
|
|
if( *pinput == 10 )
|
|
++pinput;
|
|
}
|
|
|
|
|
|
void MountParser::ReadWordQuote(std::wstring & res)
|
|
{
|
|
++pinput;
|
|
|
|
while( *pinput && *pinput!=10 && *pinput!='\"' )
|
|
{
|
|
if( pinput[0]=='\\' && pinput[1]=='\"' )
|
|
{
|
|
res += '\"';
|
|
pinput += 2;
|
|
}
|
|
else
|
|
if( pinput[0]=='\\' && pinput[1]=='\\' )
|
|
{
|
|
res += '\\';
|
|
pinput += 2;
|
|
}
|
|
else
|
|
{
|
|
res += *pinput;
|
|
pinput += 1;
|
|
}
|
|
}
|
|
|
|
if( *pinput == '"' )
|
|
++pinput;
|
|
}
|
|
|
|
|
|
// a white character is the separator
|
|
void MountParser::ReadWordWhite(std::wstring & res)
|
|
{
|
|
while( *pinput && *pinput!=10 && !IsWhite(*pinput) )
|
|
{
|
|
res += *pinput;
|
|
++pinput;
|
|
}
|
|
}
|
|
|
|
|
|
// the comma or the second bracket ')' are the separators
|
|
void MountParser::ReadWordComma(std::wstring & res)
|
|
{
|
|
while( *pinput && *pinput!=10 && *pinput!=',' && *pinput!=')' )
|
|
{
|
|
res += *pinput;
|
|
++pinput;
|
|
}
|
|
|
|
// trimming last white characters
|
|
// (white characters can be in the middle of the string)
|
|
TrimWhite(res);
|
|
}
|
|
|
|
|
|
void MountParser::ReadWord(std::wstring & res, bool comma_bracket_separator)
|
|
{
|
|
res.clear();
|
|
SkipWhite();
|
|
|
|
if( *pinput == '"' )
|
|
{
|
|
ReadWordQuote(res);
|
|
}
|
|
else
|
|
if( comma_bracket_separator )
|
|
{
|
|
ReadWordComma(res);
|
|
}
|
|
else
|
|
{
|
|
ReadWordWhite(res);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
void MountParser::ReadParamArgsLoop(Mount::ParamRow::ParamArg & args)
|
|
{
|
|
SkipWhite();
|
|
|
|
while( *pinput && *pinput!=10 && *pinput!=')' )
|
|
{
|
|
ReadWord(temp_arg, true);
|
|
|
|
if( !temp_arg.empty() )
|
|
args.push_back(temp_arg);
|
|
|
|
if( *pinput == ',' )
|
|
++pinput;
|
|
}
|
|
}
|
|
|
|
|
|
void MountParser::ReadParamArgs(Mount::ParamRow::ParamArg & args)
|
|
{
|
|
SkipWhite();
|
|
args.clear();
|
|
|
|
|
|
if( *pinput == '(' )
|
|
{
|
|
++pinput;
|
|
ReadParamArgsLoop(args);
|
|
|
|
if( *pinput != ')' )
|
|
{
|
|
// there should be ')' at the end
|
|
// temporarily we do nothing
|
|
}
|
|
else
|
|
{
|
|
++pinput;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void MountParser::ReadParamName(std::wstring & res)
|
|
{
|
|
SkipWhite();
|
|
res.clear();
|
|
|
|
while( *pinput && *pinput!=10 && *pinput!=',' && *pinput!='(' && !IsWhite(*pinput) )
|
|
{
|
|
res += *pinput;
|
|
++pinput;
|
|
}
|
|
}
|
|
|
|
|
|
void MountParser::ReadParam(std::wstring & res, Mount::ParamRow::ParamArg & args)
|
|
{
|
|
ReadParamName(res);
|
|
|
|
if( res.empty() )
|
|
return;
|
|
|
|
ReadParamArgs(args);
|
|
|
|
SkipWhite();
|
|
|
|
if( *pinput == ',' )
|
|
++pinput;
|
|
}
|
|
|
|
|
|
int MountParser::FindIndex(const std::vector<std::wstring> * tab, const std::wstring & value)
|
|
{
|
|
for(size_t i=0 ; i < tab->size() ; ++i)
|
|
{
|
|
if( (*tab)[i] == value )
|
|
return static_cast<int>(i);
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
bool MountParser::ReadMountType()
|
|
{
|
|
ReadWord(temp);
|
|
|
|
if( temp.empty() )
|
|
{
|
|
// an empty line (some white characters only)
|
|
return false;
|
|
}
|
|
|
|
mount.type = FindIndex(mount_type_tab, temp);
|
|
|
|
if( mount.type != -1 )
|
|
{
|
|
log << log3 << "MP: mount type: " << (*mount_type_tab)[mount.type] << logend;
|
|
}
|
|
else
|
|
{
|
|
log << log1 << "MP: unknown mount type: " << temp << logend;
|
|
|
|
// IMPROVE ME there is no slog now
|
|
//slog << logerror << T("unknown_mount_type") << ": " << temp << logend;
|
|
}
|
|
|
|
return mount.type != -1;
|
|
}
|
|
|
|
|
|
|
|
bool MountParser::ReadMountPoint()
|
|
{
|
|
ReadWord(last_dir);
|
|
|
|
pdir = dirs->GetDir(last_dir);
|
|
|
|
if( pdir )
|
|
{
|
|
mount.dir_id = pdir->id;
|
|
log << log3 << "MP: mount point (directory): " << last_dir << logend;
|
|
}
|
|
else
|
|
{
|
|
log << log1 << "MP: there is no such a mount point (directory): " << last_dir << logend;
|
|
|
|
// IMPROVE ME there is no slog now
|
|
//slog << logerror << T("no_such_dir") << ": " << last_dir << logend;
|
|
}
|
|
|
|
return pdir != 0;
|
|
}
|
|
|
|
|
|
|
|
bool MountParser::ReadFs()
|
|
{
|
|
ReadWord(temp);
|
|
mount.fs = FindIndex(mount_fs_tab, temp);
|
|
|
|
if( mount.fs != -1 )
|
|
{
|
|
log << log2 << "MP: file system: " << (*mount_fs_tab)[mount.fs] << logend;
|
|
}
|
|
else
|
|
{
|
|
log << log1 << "MP: unknown filesystem: " << temp << logend;
|
|
|
|
// IMPROVE ME there is no slog now
|
|
//slog << logerror << T("unknown_filesystem") << ": " << temp << " (" << last_dir << ")" << logend;
|
|
}
|
|
|
|
return mount.fs != -1;
|
|
}
|
|
|
|
|
|
|
|
void MountParser::LogMountParams()
|
|
{
|
|
size_t i;
|
|
|
|
log << log3 << "MP: mount param: " << temp << "(";
|
|
|
|
for(i=0 ; i<param_args.size() ; ++i)
|
|
{
|
|
log << param_args[i];
|
|
|
|
if( i != param_args.size()-1 )
|
|
log << ",";
|
|
}
|
|
|
|
log << ")" << logend;
|
|
}
|
|
|
|
|
|
|
|
void MountParser::ReadMountParams()
|
|
{
|
|
mount.ClearParams();
|
|
|
|
for( ReadParam(temp, param_args) ; !temp.empty() ; ReadParam(temp, param_args) )
|
|
{
|
|
int code = FindIndex(mount_par_tab, temp);
|
|
|
|
if( code != -1 )
|
|
{
|
|
mount.param[code].defined = true;
|
|
mount.param[code].arg = param_args;
|
|
LogMountParams();
|
|
}
|
|
else
|
|
{
|
|
log << log1 << "MP: unknown mount param: " << temp << logend;
|
|
|
|
// IMPROVE ME there is no slog now
|
|
//slog << logwarning << T("unknown_mount_param") << ": " << temp << " (" << T("skipped") << ")" << logend;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void MountParser::AddParams(Mount::Param & src, Mount::Param & dst)
|
|
{
|
|
if( src.size() != dst.size() )
|
|
{
|
|
log << log1 << "MP: addparams: incorrect sizes" << logend;
|
|
return;
|
|
}
|
|
|
|
for(size_t p=0 ; p < src.size() ; ++p)
|
|
{
|
|
if( src[p].defined && !dst[p].defined )
|
|
dst[p] = src[p];
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
bool MountParser::AddParamsBefore(long dir_id)
|
|
{
|
|
std::map<long, Mount>::iterator i = poutput->find(dir_id);
|
|
|
|
if( i == poutput->end() )
|
|
return false;
|
|
|
|
AddParams(i->second.param, mount_inserted.first->second.param);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
adding all non-existing parameters to this mount point from parents
|
|
*/
|
|
void MountParser::AddParamsBefore()
|
|
{
|
|
if( !pdir )
|
|
return;
|
|
|
|
Item * dir;
|
|
long dir_id = pdir->parent_id;
|
|
|
|
while( dir_id != -1 )
|
|
{
|
|
if( AddParamsBefore(dir_id) )
|
|
{
|
|
// we don't have to check others parents
|
|
// the parameters are already copied
|
|
break;
|
|
}
|
|
|
|
dir = dirs->GetDir(dir_id);
|
|
|
|
if( !dir )
|
|
break;
|
|
|
|
dir_id = dir->parent_id;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
adding all non-existing parameters to childs (childs to this mount point)
|
|
*/
|
|
void MountParser::AddParamsAfter()
|
|
{
|
|
std::map<long, Mount>::iterator i = poutput->begin();
|
|
|
|
for( ; i != poutput->end() ; ++i)
|
|
{
|
|
if( dirs->IsChild(mount_inserted.first->second.dir_id, i->first) )
|
|
AddParams(mount_inserted.first->second.param, i->second.param);
|
|
}
|
|
}
|
|
|
|
|
|
void MountParser::ReadRow()
|
|
{
|
|
if( ReadMountType() && ReadMountPoint() && ReadFs() )
|
|
{
|
|
ReadMountParams();
|
|
|
|
if( skip_static && mount.type==static_mount_id )
|
|
{
|
|
log << log1 << "MP: static mount points are skipped (dont_use_static_dirs in config is true)" << logend;
|
|
|
|
// IMPROVE ME there is no slog now
|
|
//slog << logwarning << T("skipped_static_mount") << ": " << last_dir << logend;
|
|
}
|
|
else
|
|
{
|
|
mount_inserted = poutput->insert( std::make_pair(mount.dir_id, mount) );
|
|
|
|
if( mount_inserted.second )
|
|
{
|
|
AddParamsBefore();
|
|
AddParamsAfter();
|
|
}
|
|
else
|
|
{
|
|
log << log1 << "MP: this mount point exists (skipped)" << logend;
|
|
|
|
// IMPROVE ME there is no slog now
|
|
//slog << logwarning << T("mount_exists") << ": " << last_dir << " (" << T("skipped") << ")" << logend;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
SkipLine();
|
|
}
|
|
|
|
|
|
|
|
|
|
void MountParser::Parse(const std::wstring & input, std::map<long, Mount> & output)
|
|
{
|
|
if( !dirs || !mount_type_tab || !mount_fs_tab || !mount_par_tab )
|
|
{
|
|
log << log1 << "MP: input tables not set" << logend;
|
|
return;
|
|
}
|
|
|
|
pinput = input.c_str();
|
|
poutput = &output;
|
|
mount.param.resize(mount_par_tab->size());
|
|
mount.ClearParams();
|
|
poutput->clear();
|
|
|
|
while( *pinput )
|
|
ReadRow();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace Winix
|
|
|