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