1 /* Copyright (C) 2014 InfiniDB, Inc.
2 
3    This program is free software; you can redistribute it and/or
4    modify it under the terms of the GNU General Public License
5    as published by the Free Software Foundation; version 2 of
6    the License.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 
13    You should have received a copy of the GNU General Public License
14    along with this program; if not, write to the Free Software
15    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
16    MA 02110-1301, USA. */
17 
18 #include <unistd.h>
19 #include <string>
20 //#define NDEBUG
21 #include <cassert>
22 #include <climits>
23 using namespace std;
24 
25 #include <boost/tokenizer.hpp>
26 #include <boost/filesystem.hpp>
27 using namespace boost;
28 namespace fs = boost::filesystem;
29 
30 #include "fsutils.h"
31 #include "exceptclasses.h"
32 
33 namespace
34 {
35 
resolveInDir(const string & dir,const string & name)36 const string resolveInDir(const string& dir, const string& name)
37 {
38     idbassert(!dir.empty() && !name.empty());
39     string ret;
40     fs::path path(dir);
41 
42     if (!fs::exists(path))
43         return ret;
44 
45     idbassert(fs::exists(path));
46     path /= name;
47 
48     if (!fs::exists(path))
49         return ret;
50 
51     idbassert(fs::exists(path));
52 #ifndef _MSC_VER
53 
54     if (!fs::is_symlink(path))
55         return ret;
56 
57     idbassert(fs::is_symlink(path));
58     char* realname = (char*)alloca(PATH_MAX + 1);
59     ssize_t realnamelen = readlink(path.string().c_str(), realname, PATH_MAX);
60 
61     if (realnamelen <= 0)
62         return ret;
63 
64     realname[realnamelen] = 0;
65     fs::path linkname(realname);
66     fs::path realpath("/dev");
67     realpath /= linkname.filename();
68     ret = realpath.string();
69 #endif
70     return ret;
71 }
72 
label2dev(const string & name)73 inline const string label2dev(const string& name)
74 {
75     return resolveInDir("/dev/disk/by-label", name);
76 }
77 
uuid2dev(const string & name)78 inline const string uuid2dev(const string& name)
79 {
80     return resolveInDir("/dev/disk/by-uuid", name);
81 }
82 
83 }
84 
85 namespace fsutils
86 {
87 
symname2devname(const string & sympath)88 const string symname2devname(const string& sympath)
89 {
90     string ret;
91 #ifndef _MSC_VER
92     typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
93     boost::char_separator<char> sep("=");
94     tokenizer tokens(sympath, sep);
95     tokenizer::iterator tok_iter = tokens.begin();
96 
97     idbassert(tok_iter != tokens.end());
98     string symtype = *tok_iter;
99 
100     if (symtype != "LABEL" && symtype != "UUID")
101         return ret;
102 
103     idbassert(symtype == "LABEL" || symtype == "UUID");
104 
105     ++tok_iter;
106     idbassert(tok_iter != tokens.end());
107     string symname = *tok_iter;
108 
109     ++tok_iter;
110     idbassert(tok_iter == tokens.end());
111 
112     if (symtype == "LABEL")
113         ret = label2dev(symname);
114     else if (symtype == "UUID")
115         ret = uuid2dev(symname);
116 
117 #endif
118     return ret;
119 }
120 
121 }
122 
123