Directory.cpp 3.59 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*****************************************************************************
 * Media Library
 *****************************************************************************
 * Copyright (C) 2015 Hugo Beauzée-Luyssen, Videolabs
 *
 * Authors: Hugo Beauzée-Luyssen<hugo@beauzee.fr>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

23
#include "Directory.h"
24
#include "Media.h"
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
25
#include "Device.h"
26
27
28
29
30

#include <cstring>
#include <cstdlib>
#include <dirent.h>
#include <limits.h>
31
32
#include <sys/stat.h>
#include <unistd.h>
33
34
35
36
37
38
39

namespace fs
{

Directory::Directory( const std::string& path )
    : m_path( toAbsolute( path ) )
{
40
41
42
43
44
45
#ifndef NDEBUG
    struct stat s;
    lstat( m_path.c_str(), &s );
    if ( S_ISDIR( s.st_mode ) == false )
        throw std::runtime_error( "The provided path isn't a directory" );
#endif
46
47
}

48
49
50
51
52
const std::string&Directory::path() const
{
    return m_path;
}

53
const std::vector<std::string>& Directory::files()
54
{
55
56
    if ( m_dirs.size() == 0 && m_files.size() == 0 )
        read();
57
58
59
    return m_files;
}

60
const std::vector<std::string>&Directory::dirs()
61
{
62
63
    if ( m_dirs.size() == 0 && m_files.size() == 0 )
        read();
64
65
66
    return m_dirs;
}

Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
67
std::shared_ptr<IDevice> Directory::device() const
68
69
{
    //FIXME: Cache this?
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
70
    return Device::fromPath( m_path );
71
72
}

73
74
std::string Directory::toAbsolute(const std::string& path)
{
75
76
    char abs[PATH_MAX];
    if ( realpath( path.c_str(), abs ) == nullptr )
77
78
79
80
81
82
    {
        std::string err( "Failed to convert to absolute path" );
        err += "(" + path + "): ";
        err += strerror(errno);
        throw std::runtime_error( err );
    }
83
    return std::string{ abs };
84
85
86
}

void Directory::read()
87
88
89
{
    auto dir = std::unique_ptr<DIR, int(*)(DIR*)>( opendir( m_path.c_str() ), closedir );
    if ( dir == nullptr )
90
91
92
93
94
95
    {
        std::string err( "Failed to open directory " );
        err += m_path;
        err += strerror(errno);
        throw std::runtime_error( err );
    }
96
97
98
99
100
101
102
103
104
105

    dirent* result = nullptr;

    while ( ( result = readdir( dir.get() ) ) != nullptr )
    {
        if ( strcmp( result->d_name, "." ) == 0 ||
             strcmp( result->d_name, ".." ) == 0 )
        {
            continue;
        }
106
107
        std::string path = m_path + "/" + result->d_name;

108
109
#if defined(_DIRENT_HAVE_D_TYPE) && defined(_BSD_SOURCE)
        if ( result->d_type == DT_DIR )
110
        {
111
112
#else
        struct stat s;
113
        if ( lstat( path.c_str(), &s ) != 0 )
114
        {
115
116
            if ( errno == EACCES )
                continue;
117
            std::string err( "Failed to get file info " );
118
            err += path + ": ";
119
120
121
            err += strerror(errno);
            throw std::runtime_error( err );
        }
122
123
124
        if ( S_ISDIR( s.st_mode ) )
        {
#endif
125
            m_dirs.emplace_back( toAbsolute( path ) );
126
        }
127
128
        else
        {
129
            m_files.emplace_back( toAbsolute( path ) );
130
        }
131
132
133
134
    }
}

}