/* * This file is a part of Winix * and is distributed under the 2-Clause BSD licence. * Author: Tomasz Sowa */ /* * Copyright (c) 2010-2014, 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" 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 & tab) { mount_type_tab = &tab; } void MountParser::SetMountFsTab(const std::vector & tab) { mount_fs_tab = &tab; } void MountParser::SetMountParTab(const std::vector & 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 * tab, const std::wstring & value) { for(size_t i=0 ; i < tab->size() ; ++i) { if( (*tab)[i] == value ) return static_cast(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::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::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 & 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