File: dir.cc

package info (click to toggle)
zbackup 1.5-4
  • links: PTS
  • area: main
  • in suites: forky, sid
  • size: 868 kB
  • sloc: cpp: 6,957; ansic: 468; python: 207; makefile: 10
file content (139 lines) | stat: -rw-r--r-- 2,716 bytes parent folder | download | duplicates (2)
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 <ikm@zbackup.org> 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;
  }
}

}