forked from zbackup/zbackup
-
Notifications
You must be signed in to change notification settings - Fork 0
/
dir.cc
139 lines (109 loc) · 2.65 KB
/
dir.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// Copyright (c) 2012-2014 Konstantin Isakov <[email protected]> and ZBackup contributors, see CONTRIBUTORS
// Part of ZBackup. Licensed under GNU GPLv2 or later + OpenSSL, see LICENSE
#include <fcntl.h>
#include <libgen.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <vector>
#include "dir.hh"
DIR * dir;
namespace Dir {
bool exists( string const & name )
{
struct stat buf;
return stat( name.c_str(), &buf ) == 0 && S_ISDIR( buf.st_mode );
}
void create( string const & name )
{
if ( mkdir( name.c_str(), 0777 ) != 0 )
throw exCantCreate( name );
}
void remove( string const & name )
{
if ( rmdir( name.c_str() ) != 0 )
throw exCantRemove( name );
}
string addPath( string const & first, string const & second )
{
if ( first.empty() )
return second;
if ( second.empty() )
return first;
if ( first[ first.size() - 1 ] == separator() )
return first + second;
else
return first + separator() + second;
}
string getRealPath( string const & path )
{
if ( char * r = realpath( path.c_str(), NULL ) )
{
string result( r );
free( r );
return result;
}
else
throw exCantGetRealPath( path );
}
string getDirName( string const & path )
{
char const * c = path.c_str();
std::vector< char > copy( c, c + path.size() + 1 );
return dirname( copy.data() );
}
string getBaseName( string const & path )
{
char const * c = path.c_str();
std::vector< char > copy( c, c + path.size() + 1 );
return basename( copy.data() );
}
bool isDirEmpty( string const & path )
{
Listing lst(path);
Entry tmp;
return !lst.getNext(tmp);
}
Listing::Listing( string const & dirName ): dirName( dirName )
{
dir = opendir( dirName.c_str() );
if ( !dir )
throw exCantList( dirName );
}
Listing::~Listing()
{
closedir( dir );
}
bool Listing::getNext( Entry & result )
{
dirent entry;
dirent * entryPtr;
struct stat entryStats;
for ( ; ; )
{
if ( readdir_r( dir, &entry, &entryPtr ) != 0 )
throw exCantList( dirName );
if ( !entryPtr )
return false;
#ifndef __APPLE__
if ( fstatat( dirfd( dir ), entry.d_name, &entryStats,
AT_SYMLINK_NOFOLLOW ) != 0 )
#else
if ( lstat( addPath( dirName, entry.d_name ).c_str(),
&entryStats ) != 0)
#endif
throw exCantList( dirName );
bool isDir = S_ISDIR( entryStats.st_mode );
bool isSymLink = S_ISLNK( entryStats.st_mode );
if ( isDir &&
( entry.d_name[ 0 ] == '.' &&
( !entry.d_name[ 1 ] || entry.d_name[ 1 ] == '.' ) ) )
{
// Skip the . or .. entries
continue;
}
result = Entry( entry.d_name, isDir, isSymLink );
return true;
}
}
}