1c243e490SMarcel Moolenaar // Copyright (c) 2007 The NetBSD Foundation, Inc.
2c243e490SMarcel Moolenaar // All rights reserved.
3c243e490SMarcel Moolenaar //
4c243e490SMarcel Moolenaar // Redistribution and use in source and binary forms, with or without
5c243e490SMarcel Moolenaar // modification, are permitted provided that the following conditions
6c243e490SMarcel Moolenaar // are met:
7c243e490SMarcel Moolenaar // 1. Redistributions of source code must retain the above copyright
8c243e490SMarcel Moolenaar // notice, this list of conditions and the following disclaimer.
9c243e490SMarcel Moolenaar // 2. Redistributions in binary form must reproduce the above copyright
10c243e490SMarcel Moolenaar // notice, this list of conditions and the following disclaimer in the
11c243e490SMarcel Moolenaar // documentation and/or other materials provided with the distribution.
12c243e490SMarcel Moolenaar //
13c243e490SMarcel Moolenaar // THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
14c243e490SMarcel Moolenaar // CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
15c243e490SMarcel Moolenaar // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16c243e490SMarcel Moolenaar // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17c243e490SMarcel Moolenaar // IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
18c243e490SMarcel Moolenaar // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19c243e490SMarcel Moolenaar // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
20c243e490SMarcel Moolenaar // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21c243e490SMarcel Moolenaar // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
22c243e490SMarcel Moolenaar // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23c243e490SMarcel Moolenaar // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
24c243e490SMarcel Moolenaar // IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*0677dfd1SJulio Merino
26*0677dfd1SJulio Merino #include "atf-c++/detail/fs.hpp"
27c243e490SMarcel Moolenaar
28c243e490SMarcel Moolenaar #if defined(HAVE_CONFIG_H)
29*0677dfd1SJulio Merino #include "config.h"
30c243e490SMarcel Moolenaar #endif
31c243e490SMarcel Moolenaar
32c243e490SMarcel Moolenaar extern "C" {
33c243e490SMarcel Moolenaar #include <sys/param.h>
34c243e490SMarcel Moolenaar #include <sys/types.h>
35c243e490SMarcel Moolenaar #include <sys/mount.h>
36c243e490SMarcel Moolenaar #include <sys/stat.h>
37c243e490SMarcel Moolenaar #include <sys/wait.h>
38c243e490SMarcel Moolenaar #include <dirent.h>
39c243e490SMarcel Moolenaar #include <libgen.h>
40c243e490SMarcel Moolenaar #include <unistd.h>
41c243e490SMarcel Moolenaar }
42c243e490SMarcel Moolenaar
43c243e490SMarcel Moolenaar #include <cerrno>
44c243e490SMarcel Moolenaar #include <cstdlib>
45c243e490SMarcel Moolenaar #include <cstring>
46c243e490SMarcel Moolenaar
47c243e490SMarcel Moolenaar extern "C" {
48*0677dfd1SJulio Merino #include "atf-c/error.h"
49c243e490SMarcel Moolenaar }
50c243e490SMarcel Moolenaar
51*0677dfd1SJulio Merino #include "atf-c++/detail/env.hpp"
52*0677dfd1SJulio Merino #include "atf-c++/detail/exceptions.hpp"
53*0677dfd1SJulio Merino #include "atf-c++/detail/process.hpp"
54*0677dfd1SJulio Merino #include "atf-c++/detail/sanity.hpp"
55*0677dfd1SJulio Merino #include "atf-c++/detail/text.hpp"
56*0677dfd1SJulio Merino #include "atf-c++/utils.hpp"
57c243e490SMarcel Moolenaar
58c243e490SMarcel Moolenaar namespace impl = atf::fs;
59c243e490SMarcel Moolenaar #define IMPL_NAME "atf::fs"
60c243e490SMarcel Moolenaar
61c243e490SMarcel Moolenaar // ------------------------------------------------------------------------
62c243e490SMarcel Moolenaar // Auxiliary functions.
63c243e490SMarcel Moolenaar // ------------------------------------------------------------------------
64c243e490SMarcel Moolenaar
65c243e490SMarcel Moolenaar static bool safe_access(const impl::path&, int, int);
66c243e490SMarcel Moolenaar
67c243e490SMarcel Moolenaar //!
68c243e490SMarcel Moolenaar //! \brief A controlled version of access(2).
69c243e490SMarcel Moolenaar //!
70c243e490SMarcel Moolenaar //! This function reimplements the standard access(2) system call to
71c243e490SMarcel Moolenaar //! safely control its exit status and raise an exception in case of
72c243e490SMarcel Moolenaar //! failure.
73c243e490SMarcel Moolenaar //!
74c243e490SMarcel Moolenaar static
75c243e490SMarcel Moolenaar bool
safe_access(const impl::path & p,int mode,int experr)76c243e490SMarcel Moolenaar safe_access(const impl::path& p, int mode, int experr)
77c243e490SMarcel Moolenaar {
78c243e490SMarcel Moolenaar bool ok;
79c243e490SMarcel Moolenaar
80c243e490SMarcel Moolenaar atf_error_t err = atf_fs_eaccess(p.c_path(), mode);
81c243e490SMarcel Moolenaar if (atf_is_error(err)) {
82c243e490SMarcel Moolenaar if (atf_error_is(err, "libc")) {
83c243e490SMarcel Moolenaar if (atf_libc_error_code(err) == experr) {
84c243e490SMarcel Moolenaar atf_error_free(err);
85c243e490SMarcel Moolenaar ok = false;
86c243e490SMarcel Moolenaar } else {
87c243e490SMarcel Moolenaar atf::throw_atf_error(err);
88c243e490SMarcel Moolenaar // XXX Silence warning; maybe throw_atf_error should be
89c243e490SMarcel Moolenaar // an exception and not a function.
90c243e490SMarcel Moolenaar ok = false;
91c243e490SMarcel Moolenaar }
92c243e490SMarcel Moolenaar } else {
93c243e490SMarcel Moolenaar atf::throw_atf_error(err);
94c243e490SMarcel Moolenaar // XXX Silence warning; maybe throw_atf_error should be
95c243e490SMarcel Moolenaar // an exception and not a function.
96c243e490SMarcel Moolenaar ok = false;
97c243e490SMarcel Moolenaar }
98c243e490SMarcel Moolenaar } else
99c243e490SMarcel Moolenaar ok = true;
100c243e490SMarcel Moolenaar
101c243e490SMarcel Moolenaar return ok;
102c243e490SMarcel Moolenaar }
103c243e490SMarcel Moolenaar
104c243e490SMarcel Moolenaar // ------------------------------------------------------------------------
105c243e490SMarcel Moolenaar // The "path" class.
106c243e490SMarcel Moolenaar // ------------------------------------------------------------------------
107c243e490SMarcel Moolenaar
path(const std::string & s)108c243e490SMarcel Moolenaar impl::path::path(const std::string& s)
109c243e490SMarcel Moolenaar {
110c243e490SMarcel Moolenaar atf_error_t err = atf_fs_path_init_fmt(&m_path, "%s", s.c_str());
111c243e490SMarcel Moolenaar if (atf_is_error(err))
112c243e490SMarcel Moolenaar throw_atf_error(err);
113c243e490SMarcel Moolenaar }
114c243e490SMarcel Moolenaar
path(const path & p)115c243e490SMarcel Moolenaar impl::path::path(const path& p)
116c243e490SMarcel Moolenaar {
117c243e490SMarcel Moolenaar atf_error_t err = atf_fs_path_copy(&m_path, &p.m_path);
118c243e490SMarcel Moolenaar if (atf_is_error(err))
119c243e490SMarcel Moolenaar throw_atf_error(err);
120c243e490SMarcel Moolenaar }
121c243e490SMarcel Moolenaar
path(const atf_fs_path_t * p)122c243e490SMarcel Moolenaar impl::path::path(const atf_fs_path_t *p)
123c243e490SMarcel Moolenaar {
124c243e490SMarcel Moolenaar atf_error_t err = atf_fs_path_copy(&m_path, p);
125c243e490SMarcel Moolenaar if (atf_is_error(err))
126c243e490SMarcel Moolenaar throw_atf_error(err);
127c243e490SMarcel Moolenaar }
128c243e490SMarcel Moolenaar
~path(void)129c243e490SMarcel Moolenaar impl::path::~path(void)
130c243e490SMarcel Moolenaar {
131c243e490SMarcel Moolenaar atf_fs_path_fini(&m_path);
132c243e490SMarcel Moolenaar }
133c243e490SMarcel Moolenaar
134c243e490SMarcel Moolenaar const char*
c_str(void) const135c243e490SMarcel Moolenaar impl::path::c_str(void)
136c243e490SMarcel Moolenaar const
137c243e490SMarcel Moolenaar {
138c243e490SMarcel Moolenaar return atf_fs_path_cstring(&m_path);
139c243e490SMarcel Moolenaar }
140c243e490SMarcel Moolenaar
141c243e490SMarcel Moolenaar const atf_fs_path_t*
c_path(void) const142c243e490SMarcel Moolenaar impl::path::c_path(void)
143c243e490SMarcel Moolenaar const
144c243e490SMarcel Moolenaar {
145c243e490SMarcel Moolenaar return &m_path;
146c243e490SMarcel Moolenaar }
147c243e490SMarcel Moolenaar
148c243e490SMarcel Moolenaar std::string
str(void) const149c243e490SMarcel Moolenaar impl::path::str(void)
150c243e490SMarcel Moolenaar const
151c243e490SMarcel Moolenaar {
152c243e490SMarcel Moolenaar return c_str();
153c243e490SMarcel Moolenaar }
154c243e490SMarcel Moolenaar
155c243e490SMarcel Moolenaar bool
is_absolute(void) const156c243e490SMarcel Moolenaar impl::path::is_absolute(void)
157c243e490SMarcel Moolenaar const
158c243e490SMarcel Moolenaar {
159c243e490SMarcel Moolenaar return atf_fs_path_is_absolute(&m_path);
160c243e490SMarcel Moolenaar }
161c243e490SMarcel Moolenaar
162c243e490SMarcel Moolenaar bool
is_root(void) const163c243e490SMarcel Moolenaar impl::path::is_root(void)
164c243e490SMarcel Moolenaar const
165c243e490SMarcel Moolenaar {
166c243e490SMarcel Moolenaar return atf_fs_path_is_root(&m_path);
167c243e490SMarcel Moolenaar }
168c243e490SMarcel Moolenaar
169c243e490SMarcel Moolenaar impl::path
branch_path(void) const170c243e490SMarcel Moolenaar impl::path::branch_path(void)
171c243e490SMarcel Moolenaar const
172c243e490SMarcel Moolenaar {
173c243e490SMarcel Moolenaar atf_fs_path_t bp;
174c243e490SMarcel Moolenaar atf_error_t err;
175c243e490SMarcel Moolenaar
176c243e490SMarcel Moolenaar err = atf_fs_path_branch_path(&m_path, &bp);
177c243e490SMarcel Moolenaar if (atf_is_error(err))
178c243e490SMarcel Moolenaar throw_atf_error(err);
179c243e490SMarcel Moolenaar
180c243e490SMarcel Moolenaar path p(atf_fs_path_cstring(&bp));
181c243e490SMarcel Moolenaar atf_fs_path_fini(&bp);
182c243e490SMarcel Moolenaar return p;
183c243e490SMarcel Moolenaar }
184c243e490SMarcel Moolenaar
185c243e490SMarcel Moolenaar std::string
leaf_name(void) const186c243e490SMarcel Moolenaar impl::path::leaf_name(void)
187c243e490SMarcel Moolenaar const
188c243e490SMarcel Moolenaar {
189c243e490SMarcel Moolenaar atf_dynstr_t ln;
190c243e490SMarcel Moolenaar atf_error_t err;
191c243e490SMarcel Moolenaar
192c243e490SMarcel Moolenaar err = atf_fs_path_leaf_name(&m_path, &ln);
193c243e490SMarcel Moolenaar if (atf_is_error(err))
194c243e490SMarcel Moolenaar throw_atf_error(err);
195c243e490SMarcel Moolenaar
196c243e490SMarcel Moolenaar std::string s(atf_dynstr_cstring(&ln));
197c243e490SMarcel Moolenaar atf_dynstr_fini(&ln);
198c243e490SMarcel Moolenaar return s;
199c243e490SMarcel Moolenaar }
200c243e490SMarcel Moolenaar
201c243e490SMarcel Moolenaar impl::path
to_absolute(void) const202c243e490SMarcel Moolenaar impl::path::to_absolute(void)
203c243e490SMarcel Moolenaar const
204c243e490SMarcel Moolenaar {
205c243e490SMarcel Moolenaar atf_fs_path_t pa;
206c243e490SMarcel Moolenaar
207c243e490SMarcel Moolenaar atf_error_t err = atf_fs_path_to_absolute(&m_path, &pa);
208c243e490SMarcel Moolenaar if (atf_is_error(err))
209c243e490SMarcel Moolenaar throw_atf_error(err);
210c243e490SMarcel Moolenaar
211c243e490SMarcel Moolenaar path p(atf_fs_path_cstring(&pa));
212c243e490SMarcel Moolenaar atf_fs_path_fini(&pa);
213c243e490SMarcel Moolenaar return p;
214c243e490SMarcel Moolenaar }
215c243e490SMarcel Moolenaar
216c243e490SMarcel Moolenaar impl::path&
operator =(const path & p)217c243e490SMarcel Moolenaar impl::path::operator=(const path& p)
218c243e490SMarcel Moolenaar {
219c243e490SMarcel Moolenaar atf_fs_path_t tmp;
220c243e490SMarcel Moolenaar
221c243e490SMarcel Moolenaar atf_error_t err = atf_fs_path_init_fmt(&tmp, "%s", p.c_str());
222c243e490SMarcel Moolenaar if (atf_is_error(err))
223c243e490SMarcel Moolenaar throw_atf_error(err);
224c243e490SMarcel Moolenaar else {
225c243e490SMarcel Moolenaar atf_fs_path_fini(&m_path);
226c243e490SMarcel Moolenaar m_path = tmp;
227c243e490SMarcel Moolenaar }
228c243e490SMarcel Moolenaar
229c243e490SMarcel Moolenaar return *this;
230c243e490SMarcel Moolenaar }
231c243e490SMarcel Moolenaar
232c243e490SMarcel Moolenaar bool
operator ==(const path & p) const233c243e490SMarcel Moolenaar impl::path::operator==(const path& p)
234c243e490SMarcel Moolenaar const
235c243e490SMarcel Moolenaar {
236c243e490SMarcel Moolenaar return atf_equal_fs_path_fs_path(&m_path, &p.m_path);
237c243e490SMarcel Moolenaar }
238c243e490SMarcel Moolenaar
239c243e490SMarcel Moolenaar bool
operator !=(const path & p) const240c243e490SMarcel Moolenaar impl::path::operator!=(const path& p)
241c243e490SMarcel Moolenaar const
242c243e490SMarcel Moolenaar {
243c243e490SMarcel Moolenaar return !atf_equal_fs_path_fs_path(&m_path, &p.m_path);
244c243e490SMarcel Moolenaar }
245c243e490SMarcel Moolenaar
246c243e490SMarcel Moolenaar impl::path
operator /(const std::string & p) const247c243e490SMarcel Moolenaar impl::path::operator/(const std::string& p)
248c243e490SMarcel Moolenaar const
249c243e490SMarcel Moolenaar {
250c243e490SMarcel Moolenaar path p2 = *this;
251c243e490SMarcel Moolenaar
252c243e490SMarcel Moolenaar atf_error_t err = atf_fs_path_append_fmt(&p2.m_path, "%s", p.c_str());
253c243e490SMarcel Moolenaar if (atf_is_error(err))
254c243e490SMarcel Moolenaar throw_atf_error(err);
255c243e490SMarcel Moolenaar
256c243e490SMarcel Moolenaar return p2;
257c243e490SMarcel Moolenaar }
258c243e490SMarcel Moolenaar
259c243e490SMarcel Moolenaar impl::path
operator /(const path & p) const260c243e490SMarcel Moolenaar impl::path::operator/(const path& p)
261c243e490SMarcel Moolenaar const
262c243e490SMarcel Moolenaar {
263c243e490SMarcel Moolenaar path p2 = *this;
264c243e490SMarcel Moolenaar
265c243e490SMarcel Moolenaar atf_error_t err = atf_fs_path_append_fmt(&p2.m_path, "%s",
266c243e490SMarcel Moolenaar atf_fs_path_cstring(&p.m_path));
267c243e490SMarcel Moolenaar if (atf_is_error(err))
268c243e490SMarcel Moolenaar throw_atf_error(err);
269c243e490SMarcel Moolenaar
270c243e490SMarcel Moolenaar return p2;
271c243e490SMarcel Moolenaar }
272c243e490SMarcel Moolenaar
273c243e490SMarcel Moolenaar bool
operator <(const path & p) const274c243e490SMarcel Moolenaar impl::path::operator<(const path& p)
275c243e490SMarcel Moolenaar const
276c243e490SMarcel Moolenaar {
277c243e490SMarcel Moolenaar const char *s1 = atf_fs_path_cstring(&m_path);
278c243e490SMarcel Moolenaar const char *s2 = atf_fs_path_cstring(&p.m_path);
279c243e490SMarcel Moolenaar return std::strcmp(s1, s2) < 0;
280c243e490SMarcel Moolenaar }
281c243e490SMarcel Moolenaar
282c243e490SMarcel Moolenaar // ------------------------------------------------------------------------
283c243e490SMarcel Moolenaar // The "file_info" class.
284c243e490SMarcel Moolenaar // ------------------------------------------------------------------------
285c243e490SMarcel Moolenaar
286c243e490SMarcel Moolenaar const int impl::file_info::blk_type = atf_fs_stat_blk_type;
287c243e490SMarcel Moolenaar const int impl::file_info::chr_type = atf_fs_stat_chr_type;
288c243e490SMarcel Moolenaar const int impl::file_info::dir_type = atf_fs_stat_dir_type;
289c243e490SMarcel Moolenaar const int impl::file_info::fifo_type = atf_fs_stat_fifo_type;
290c243e490SMarcel Moolenaar const int impl::file_info::lnk_type = atf_fs_stat_lnk_type;
291c243e490SMarcel Moolenaar const int impl::file_info::reg_type = atf_fs_stat_reg_type;
292c243e490SMarcel Moolenaar const int impl::file_info::sock_type = atf_fs_stat_sock_type;
293c243e490SMarcel Moolenaar const int impl::file_info::wht_type = atf_fs_stat_wht_type;
294c243e490SMarcel Moolenaar
file_info(const path & p)295c243e490SMarcel Moolenaar impl::file_info::file_info(const path& p)
296c243e490SMarcel Moolenaar {
297c243e490SMarcel Moolenaar atf_error_t err;
298c243e490SMarcel Moolenaar
299c243e490SMarcel Moolenaar err = atf_fs_stat_init(&m_stat, p.c_path());
300c243e490SMarcel Moolenaar if (atf_is_error(err))
301c243e490SMarcel Moolenaar throw_atf_error(err);
302c243e490SMarcel Moolenaar }
303c243e490SMarcel Moolenaar
file_info(const file_info & fi)304c243e490SMarcel Moolenaar impl::file_info::file_info(const file_info& fi)
305c243e490SMarcel Moolenaar {
306c243e490SMarcel Moolenaar atf_fs_stat_copy(&m_stat, &fi.m_stat);
307c243e490SMarcel Moolenaar }
308c243e490SMarcel Moolenaar
~file_info(void)309c243e490SMarcel Moolenaar impl::file_info::~file_info(void)
310c243e490SMarcel Moolenaar {
311c243e490SMarcel Moolenaar atf_fs_stat_fini(&m_stat);
312c243e490SMarcel Moolenaar }
313c243e490SMarcel Moolenaar
314c243e490SMarcel Moolenaar dev_t
get_device(void) const315c243e490SMarcel Moolenaar impl::file_info::get_device(void)
316c243e490SMarcel Moolenaar const
317c243e490SMarcel Moolenaar {
318c243e490SMarcel Moolenaar return atf_fs_stat_get_device(&m_stat);
319c243e490SMarcel Moolenaar }
320c243e490SMarcel Moolenaar
321c243e490SMarcel Moolenaar ino_t
get_inode(void) const322c243e490SMarcel Moolenaar impl::file_info::get_inode(void)
323c243e490SMarcel Moolenaar const
324c243e490SMarcel Moolenaar {
325c243e490SMarcel Moolenaar return atf_fs_stat_get_inode(&m_stat);
326c243e490SMarcel Moolenaar }
327c243e490SMarcel Moolenaar
328c243e490SMarcel Moolenaar mode_t
get_mode(void) const329c243e490SMarcel Moolenaar impl::file_info::get_mode(void)
330c243e490SMarcel Moolenaar const
331c243e490SMarcel Moolenaar {
332c243e490SMarcel Moolenaar return atf_fs_stat_get_mode(&m_stat);
333c243e490SMarcel Moolenaar }
334c243e490SMarcel Moolenaar
335c243e490SMarcel Moolenaar off_t
get_size(void) const336c243e490SMarcel Moolenaar impl::file_info::get_size(void)
337c243e490SMarcel Moolenaar const
338c243e490SMarcel Moolenaar {
339c243e490SMarcel Moolenaar return atf_fs_stat_get_size(&m_stat);
340c243e490SMarcel Moolenaar }
341c243e490SMarcel Moolenaar
342c243e490SMarcel Moolenaar int
get_type(void) const343c243e490SMarcel Moolenaar impl::file_info::get_type(void)
344c243e490SMarcel Moolenaar const
345c243e490SMarcel Moolenaar {
346c243e490SMarcel Moolenaar return atf_fs_stat_get_type(&m_stat);
347c243e490SMarcel Moolenaar }
348c243e490SMarcel Moolenaar
349c243e490SMarcel Moolenaar bool
is_owner_readable(void) const350c243e490SMarcel Moolenaar impl::file_info::is_owner_readable(void)
351c243e490SMarcel Moolenaar const
352c243e490SMarcel Moolenaar {
353c243e490SMarcel Moolenaar return atf_fs_stat_is_owner_readable(&m_stat);
354c243e490SMarcel Moolenaar }
355c243e490SMarcel Moolenaar
356c243e490SMarcel Moolenaar bool
is_owner_writable(void) const357c243e490SMarcel Moolenaar impl::file_info::is_owner_writable(void)
358c243e490SMarcel Moolenaar const
359c243e490SMarcel Moolenaar {
360c243e490SMarcel Moolenaar return atf_fs_stat_is_owner_writable(&m_stat);
361c243e490SMarcel Moolenaar }
362c243e490SMarcel Moolenaar
363c243e490SMarcel Moolenaar bool
is_owner_executable(void) const364c243e490SMarcel Moolenaar impl::file_info::is_owner_executable(void)
365c243e490SMarcel Moolenaar const
366c243e490SMarcel Moolenaar {
367c243e490SMarcel Moolenaar return atf_fs_stat_is_owner_executable(&m_stat);
368c243e490SMarcel Moolenaar }
369c243e490SMarcel Moolenaar
370c243e490SMarcel Moolenaar bool
is_group_readable(void) const371c243e490SMarcel Moolenaar impl::file_info::is_group_readable(void)
372c243e490SMarcel Moolenaar const
373c243e490SMarcel Moolenaar {
374c243e490SMarcel Moolenaar return atf_fs_stat_is_group_readable(&m_stat);
375c243e490SMarcel Moolenaar }
376c243e490SMarcel Moolenaar
377c243e490SMarcel Moolenaar bool
is_group_writable(void) const378c243e490SMarcel Moolenaar impl::file_info::is_group_writable(void)
379c243e490SMarcel Moolenaar const
380c243e490SMarcel Moolenaar {
381c243e490SMarcel Moolenaar return atf_fs_stat_is_group_writable(&m_stat);
382c243e490SMarcel Moolenaar }
383c243e490SMarcel Moolenaar
384c243e490SMarcel Moolenaar bool
is_group_executable(void) const385c243e490SMarcel Moolenaar impl::file_info::is_group_executable(void)
386c243e490SMarcel Moolenaar const
387c243e490SMarcel Moolenaar {
388c243e490SMarcel Moolenaar return atf_fs_stat_is_group_executable(&m_stat);
389c243e490SMarcel Moolenaar }
390c243e490SMarcel Moolenaar
391c243e490SMarcel Moolenaar bool
is_other_readable(void) const392c243e490SMarcel Moolenaar impl::file_info::is_other_readable(void)
393c243e490SMarcel Moolenaar const
394c243e490SMarcel Moolenaar {
395c243e490SMarcel Moolenaar return atf_fs_stat_is_other_readable(&m_stat);
396c243e490SMarcel Moolenaar }
397c243e490SMarcel Moolenaar
398c243e490SMarcel Moolenaar bool
is_other_writable(void) const399c243e490SMarcel Moolenaar impl::file_info::is_other_writable(void)
400c243e490SMarcel Moolenaar const
401c243e490SMarcel Moolenaar {
402c243e490SMarcel Moolenaar return atf_fs_stat_is_other_writable(&m_stat);
403c243e490SMarcel Moolenaar }
404c243e490SMarcel Moolenaar
405c243e490SMarcel Moolenaar bool
is_other_executable(void) const406c243e490SMarcel Moolenaar impl::file_info::is_other_executable(void)
407c243e490SMarcel Moolenaar const
408c243e490SMarcel Moolenaar {
409c243e490SMarcel Moolenaar return atf_fs_stat_is_other_executable(&m_stat);
410c243e490SMarcel Moolenaar }
411c243e490SMarcel Moolenaar
412c243e490SMarcel Moolenaar // ------------------------------------------------------------------------
413c243e490SMarcel Moolenaar // The "directory" class.
414c243e490SMarcel Moolenaar // ------------------------------------------------------------------------
415c243e490SMarcel Moolenaar
directory(const path & p)416c243e490SMarcel Moolenaar impl::directory::directory(const path& p)
417c243e490SMarcel Moolenaar {
418c243e490SMarcel Moolenaar DIR* dp = ::opendir(p.c_str());
419c243e490SMarcel Moolenaar if (dp == NULL)
420c243e490SMarcel Moolenaar throw system_error(IMPL_NAME "::directory::directory(" +
421c243e490SMarcel Moolenaar p.str() + ")", "opendir(3) failed", errno);
422c243e490SMarcel Moolenaar
423c243e490SMarcel Moolenaar struct dirent* dep;
424c243e490SMarcel Moolenaar while ((dep = ::readdir(dp)) != NULL) {
425c243e490SMarcel Moolenaar path entryp = p / dep->d_name;
426c243e490SMarcel Moolenaar insert(value_type(dep->d_name, file_info(entryp)));
427c243e490SMarcel Moolenaar }
428c243e490SMarcel Moolenaar
429c243e490SMarcel Moolenaar if (::closedir(dp) == -1)
430c243e490SMarcel Moolenaar throw system_error(IMPL_NAME "::directory::directory(" +
431c243e490SMarcel Moolenaar p.str() + ")", "closedir(3) failed", errno);
432c243e490SMarcel Moolenaar }
433c243e490SMarcel Moolenaar
434c243e490SMarcel Moolenaar std::set< std::string >
names(void) const435c243e490SMarcel Moolenaar impl::directory::names(void)
436c243e490SMarcel Moolenaar const
437c243e490SMarcel Moolenaar {
438c243e490SMarcel Moolenaar std::set< std::string > ns;
439c243e490SMarcel Moolenaar
440c243e490SMarcel Moolenaar for (const_iterator iter = begin(); iter != end(); iter++)
441c243e490SMarcel Moolenaar ns.insert((*iter).first);
442c243e490SMarcel Moolenaar
443c243e490SMarcel Moolenaar return ns;
444c243e490SMarcel Moolenaar }
445c243e490SMarcel Moolenaar
446c243e490SMarcel Moolenaar // ------------------------------------------------------------------------
447c243e490SMarcel Moolenaar // Free functions.
448c243e490SMarcel Moolenaar // ------------------------------------------------------------------------
449c243e490SMarcel Moolenaar
450c243e490SMarcel Moolenaar bool
exists(const path & p)451c243e490SMarcel Moolenaar impl::exists(const path& p)
452c243e490SMarcel Moolenaar {
453c243e490SMarcel Moolenaar atf_error_t err;
454c243e490SMarcel Moolenaar bool b;
455c243e490SMarcel Moolenaar
456c243e490SMarcel Moolenaar err = atf_fs_exists(p.c_path(), &b);
457c243e490SMarcel Moolenaar if (atf_is_error(err))
458c243e490SMarcel Moolenaar throw_atf_error(err);
459c243e490SMarcel Moolenaar
460c243e490SMarcel Moolenaar return b;
461c243e490SMarcel Moolenaar }
462c243e490SMarcel Moolenaar
463c243e490SMarcel Moolenaar bool
have_prog_in_path(const std::string & prog)464c243e490SMarcel Moolenaar impl::have_prog_in_path(const std::string& prog)
465c243e490SMarcel Moolenaar {
466c243e490SMarcel Moolenaar PRE(prog.find('/') == std::string::npos);
467c243e490SMarcel Moolenaar
468c243e490SMarcel Moolenaar // Do not bother to provide a default value for PATH. If it is not
469c243e490SMarcel Moolenaar // there something is broken in the user's environment.
470c243e490SMarcel Moolenaar if (!atf::env::has("PATH"))
471c243e490SMarcel Moolenaar throw std::runtime_error("PATH not defined in the environment");
472c243e490SMarcel Moolenaar std::vector< std::string > dirs =
473c243e490SMarcel Moolenaar atf::text::split(atf::env::get("PATH"), ":");
474c243e490SMarcel Moolenaar
475c243e490SMarcel Moolenaar bool found = false;
476c243e490SMarcel Moolenaar for (std::vector< std::string >::const_iterator iter = dirs.begin();
477c243e490SMarcel Moolenaar !found && iter != dirs.end(); iter++) {
478c243e490SMarcel Moolenaar const path& dir = path(*iter);
479c243e490SMarcel Moolenaar
480c243e490SMarcel Moolenaar if (is_executable(dir / prog))
481c243e490SMarcel Moolenaar found = true;
482c243e490SMarcel Moolenaar }
483c243e490SMarcel Moolenaar return found;
484c243e490SMarcel Moolenaar }
485c243e490SMarcel Moolenaar
486c243e490SMarcel Moolenaar bool
is_executable(const path & p)487c243e490SMarcel Moolenaar impl::is_executable(const path& p)
488c243e490SMarcel Moolenaar {
489c243e490SMarcel Moolenaar if (!exists(p))
490c243e490SMarcel Moolenaar return false;
491c243e490SMarcel Moolenaar return safe_access(p, atf_fs_access_x, EACCES);
492c243e490SMarcel Moolenaar }
493c243e490SMarcel Moolenaar
494c243e490SMarcel Moolenaar void
remove(const path & p)495c243e490SMarcel Moolenaar impl::remove(const path& p)
496c243e490SMarcel Moolenaar {
497c243e490SMarcel Moolenaar if (file_info(p).get_type() == file_info::dir_type)
498c243e490SMarcel Moolenaar throw atf::system_error(IMPL_NAME "::remove(" + p.str() + ")",
499c243e490SMarcel Moolenaar "Is a directory",
500c243e490SMarcel Moolenaar EPERM);
501c243e490SMarcel Moolenaar if (::unlink(p.c_str()) == -1)
502c243e490SMarcel Moolenaar throw atf::system_error(IMPL_NAME "::remove(" + p.str() + ")",
503c243e490SMarcel Moolenaar "unlink(" + p.str() + ") failed",
504c243e490SMarcel Moolenaar errno);
505c243e490SMarcel Moolenaar }
506c243e490SMarcel Moolenaar
507c243e490SMarcel Moolenaar void
rmdir(const path & p)508c243e490SMarcel Moolenaar impl::rmdir(const path& p)
509c243e490SMarcel Moolenaar {
510c243e490SMarcel Moolenaar atf_error_t err = atf_fs_rmdir(p.c_path());
511c243e490SMarcel Moolenaar if (atf_is_error(err))
512c243e490SMarcel Moolenaar throw_atf_error(err);
513c243e490SMarcel Moolenaar }
514