1 | /* Copyright © 2003,2006-2008 Roger Leigh <rleigh@debian.org> |
---|
2 | * |
---|
3 | * schroot is free software: you can redistribute it and/or modify it |
---|
4 | * under the terms of the GNU General Public License as published by |
---|
5 | * the Free Software Foundation, either version 3 of the License, or |
---|
6 | * (at your option) any later version. |
---|
7 | * |
---|
8 | * schroot is distributed in the hope that it will be useful, but |
---|
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
11 | * 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, see |
---|
15 | * <http://www.gnu.org/licenses/>. |
---|
16 | * |
---|
17 | *********************************************************************/ |
---|
18 | |
---|
19 | #include <config.h> |
---|
20 | |
---|
21 | #include "sbuild-mntstream.h" |
---|
22 | |
---|
23 | #include <cerrno> |
---|
24 | #include <cstring> |
---|
25 | |
---|
26 | using namespace sbuild; |
---|
27 | |
---|
28 | namespace |
---|
29 | { |
---|
30 | |
---|
31 | typedef std::pair<mntstream::error_code,const char *> emap; |
---|
32 | |
---|
33 | /** |
---|
34 | * This is a list of the supported error codes. It's used to |
---|
35 | * construct the real error codes map. |
---|
36 | */ |
---|
37 | emap init_errors[] = |
---|
38 | { |
---|
39 | // TRANSLATORS: %1% = mount file name |
---|
40 | emap(mntstream::MNT_OPEN, N_("Failed to open mount file '%1%'")), |
---|
41 | // TRANSLATORS: %1% = mount file name |
---|
42 | emap(mntstream::MNT_READ, N_("Failed to read mount file '%1%'")) |
---|
43 | }; |
---|
44 | |
---|
45 | } |
---|
46 | |
---|
47 | template<> |
---|
48 | error<mntstream::error_code>::map_type |
---|
49 | error<mntstream::error_code>::error_strings |
---|
50 | (init_errors, |
---|
51 | init_errors + (sizeof(init_errors) / sizeof(init_errors[0]))); |
---|
52 | |
---|
53 | |
---|
54 | mntstream::mntentry::mntentry (struct mntent const& entry): |
---|
55 | filesystem_name(entry.mnt_fsname), |
---|
56 | directory(entry.mnt_dir), |
---|
57 | type(entry.mnt_type), |
---|
58 | options(entry.mnt_opts), |
---|
59 | dump_frequency(entry.mnt_freq), |
---|
60 | fsck_pass(entry.mnt_passno) |
---|
61 | { |
---|
62 | } |
---|
63 | |
---|
64 | |
---|
65 | mntstream::mntstream(std::string const& file): |
---|
66 | file(), |
---|
67 | mntfile(0), |
---|
68 | data(), |
---|
69 | error_status(true), |
---|
70 | eof_status(true) |
---|
71 | { |
---|
72 | open(file); |
---|
73 | } |
---|
74 | |
---|
75 | |
---|
76 | mntstream::~mntstream() |
---|
77 | { |
---|
78 | close(); |
---|
79 | } |
---|
80 | |
---|
81 | void |
---|
82 | mntstream::open(std::string const& file) |
---|
83 | { |
---|
84 | this->mntfile = setmntent(file.c_str(), "r"); |
---|
85 | if (this->mntfile == 0) |
---|
86 | { |
---|
87 | this->file.clear(); |
---|
88 | this->error_status = true; |
---|
89 | this->eof_status = true; |
---|
90 | throw error(file, MNT_OPEN, strerror(errno)); |
---|
91 | } |
---|
92 | this->file = file; |
---|
93 | this->error_status = false; |
---|
94 | this->eof_status = false; |
---|
95 | read(); |
---|
96 | } |
---|
97 | |
---|
98 | void |
---|
99 | mntstream::read(int quantity) |
---|
100 | { |
---|
101 | int i; |
---|
102 | |
---|
103 | if (this->mntfile == 0) |
---|
104 | return; |
---|
105 | |
---|
106 | for (i = 0; i < quantity; ++i) |
---|
107 | { |
---|
108 | struct mntent* entry; |
---|
109 | errno = 0; |
---|
110 | entry = getmntent(mntfile); |
---|
111 | |
---|
112 | if (entry == 0) // EOF or error |
---|
113 | { |
---|
114 | //std::cerr << "Mount file read error: "; |
---|
115 | if (errno) // error |
---|
116 | { |
---|
117 | this->error_status = true; |
---|
118 | throw error(this->file, MNT_READ, strerror(errno)); |
---|
119 | } |
---|
120 | return; |
---|
121 | } |
---|
122 | |
---|
123 | mntentry newentry(*entry); // make a mntentry |
---|
124 | this->data.push_back(newentry); // push onto the end of the list |
---|
125 | } |
---|
126 | } |
---|
127 | |
---|
128 | void |
---|
129 | mntstream::close() |
---|
130 | { |
---|
131 | if (this->mntfile) |
---|
132 | endmntent(this->mntfile); // don't throw an exception on failure |
---|
133 | // -- it could be called in the |
---|
134 | // destructor |
---|
135 | this->mntfile = 0; |
---|
136 | this->data.clear(); // clear all data |
---|
137 | this->file.clear(); |
---|
138 | this->error_status = true; |
---|
139 | this->eof_status = true; |
---|
140 | } |
---|
141 | |
---|
142 | |
---|
143 | bool |
---|
144 | mntstream::eof() const |
---|
145 | { |
---|
146 | return this->eof_status; |
---|
147 | } |
---|
148 | |
---|
149 | bool |
---|
150 | mntstream::bad() const |
---|
151 | { |
---|
152 | return this->error_status; |
---|
153 | } |
---|
154 | |
---|
155 | mntstream::operator bool () |
---|
156 | { |
---|
157 | return !(bad() || eof()); |
---|
158 | } |
---|
159 | |
---|
160 | bool |
---|
161 | mntstream::operator ! () |
---|
162 | { |
---|
163 | return bad() || eof(); |
---|
164 | } |
---|
165 | |
---|
166 | |
---|
167 | mntstream& |
---|
168 | sbuild::operator >> (mntstream& stream, |
---|
169 | mntstream::mntentry& entry) |
---|
170 | { |
---|
171 | stream.read(); // read a new entry |
---|
172 | if (stream && !stream.data.empty()) // not at end of file or bad. |
---|
173 | { |
---|
174 | entry = stream.data.front(); // assign next mntentry to entry |
---|
175 | stream.data.pop_front(); // remove the entry |
---|
176 | } |
---|
177 | else // blank the mntentry and set EOF status |
---|
178 | { |
---|
179 | entry = mntstream::mntentry(); |
---|
180 | stream.eof_status = true; |
---|
181 | } |
---|
182 | |
---|
183 | return stream; |
---|
184 | } |
---|