mirror of
https://github.com/MariaDB/server.git
synced 2025-07-08 17:02:21 +03:00
171 lines
3.5 KiB
Perl
171 lines
3.5 KiB
Perl
package NDB::Util::Dir;
|
|
|
|
use strict;
|
|
use Carp;
|
|
use Symbol;
|
|
use Errno;
|
|
use File::Basename;
|
|
|
|
require NDB::Util::Base;
|
|
|
|
use vars qw(@ISA);
|
|
@ISA = qw(NDB::Util::Base);
|
|
|
|
# constructors
|
|
|
|
my $log;
|
|
|
|
sub initmodule {
|
|
$log = NDB::Util::Log->instance;
|
|
}
|
|
|
|
NDB::Util::Dir->attributes(
|
|
path => sub { length > 0 },
|
|
);
|
|
|
|
sub new {
|
|
my $class = shift;
|
|
@_ % 2 == 0 or confess 0+@_;
|
|
my(%attr) = @_;
|
|
my $dir = $class->SUPER::new(%attr);
|
|
$dir->setpath($attr{path})
|
|
or $log->push, return undef;
|
|
return $dir;
|
|
}
|
|
|
|
sub desc {
|
|
my $dir = shift;
|
|
return $dir->getpath;
|
|
}
|
|
|
|
sub getparent {
|
|
my $dir = shift;
|
|
@_ == 0 or confess 0+@_;
|
|
my $ppath = dirname($dir->getpath);
|
|
my $pdir = NDB::Util::Dir->new(path => $ppath);
|
|
return $pdir;
|
|
}
|
|
|
|
sub getdir {
|
|
my $dir = shift;
|
|
@_ == 1 or confess 0+@_;
|
|
my($name) = @_;
|
|
my $dirpath = $dir->getpath;
|
|
my $path = $dirpath eq '.' ? $name : File::Spec->catfile($dirpath, $name);
|
|
my $entry = NDB::Util::Dir->new(path => $path);
|
|
return $entry;
|
|
}
|
|
|
|
sub getfile {
|
|
my $dir = shift;
|
|
@_ == 1 or confess 0+@_;
|
|
my($name) = @_;
|
|
my $dirpath = $dir->getpath;
|
|
my $path = $dirpath eq '.' ? $name : File::Spec->catfile($dirpath, $name);
|
|
my $entry = NDB::Util::File->new(path => $path);
|
|
return $entry;
|
|
}
|
|
|
|
# list
|
|
|
|
sub listdirs {
|
|
my $dir = shift;
|
|
@_ == 0 or confess 0+@_;
|
|
my @list = ();
|
|
my $dirpath = $dir->getpath;
|
|
my $dh = gensym();
|
|
if (! opendir($dh, $dirpath)) {
|
|
$log->put("opendir failed: $!")->push($dir);
|
|
return undef;
|
|
}
|
|
while (defined(my $name = readdir($dh))) {
|
|
if ($name eq '.' || $name eq '..') {
|
|
next;
|
|
}
|
|
my $path = $dirpath eq '.' ? $name : "$dirpath/$name";
|
|
if (! -l $path && -d $path) {
|
|
my $dir2 = NDB::Util::Dir->new(path => $path)
|
|
or $log->push, return undef;
|
|
push(@list, $dir2);
|
|
}
|
|
}
|
|
close($dh);
|
|
return \@list;
|
|
}
|
|
|
|
sub listfiles {
|
|
my $dir = shift;
|
|
@_ == 0 or confess 0+@_;
|
|
my @list = ();
|
|
my $dirpath = $dir->getpath;
|
|
my $dh = gensym();
|
|
if (! opendir($dh, $dirpath)) {
|
|
$log->put("opendir failed: $!")->push($dir);
|
|
return undef;
|
|
}
|
|
while (defined(my $name = readdir($dh))) {
|
|
if ($name eq '.' || $name eq '..') {
|
|
next;
|
|
}
|
|
my $path = $dirpath eq '.' ? $name : "$dirpath/$name";
|
|
if (! -d $path && -e $path) {
|
|
my $file2 = NDB::Util::File->new(path => $path)
|
|
or $log->push, return undef;
|
|
push(@list, $file2);
|
|
}
|
|
}
|
|
close($dh);
|
|
return \@list;
|
|
}
|
|
|
|
# create / remove
|
|
|
|
sub mkdir {
|
|
my $dir = shift;
|
|
@_ == 0 or confess 0+@_;
|
|
if (! -d $dir->getpath) {
|
|
my $pdir = $dir->getparent;
|
|
if (length($pdir->getpath) >= length($dir->getpath)) {
|
|
$log->put("mkdir looping")->push($dir);
|
|
return undef;
|
|
}
|
|
$pdir->mkdir or return undef;
|
|
if (! mkdir($dir->getpath, 0777)) {
|
|
my $errstr = "$!";
|
|
if (-d $dir->getpath) {
|
|
return 1;
|
|
}
|
|
$log->put("mkdir failed: $errstr")->push($dir);
|
|
return undef;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
sub rmdir {
|
|
my $dir = shift;
|
|
my $keep = shift; # keep top level
|
|
$log->put("remove")->push($dir)->info;
|
|
my $list;
|
|
$list = $dir->listdirs or $log->push, return undef;
|
|
for my $d (@$list) {
|
|
$d->rmdir or $log->push, return undef;
|
|
}
|
|
$list = $dir->listfiles or $log->push, return undef;
|
|
for my $f (@$list) {
|
|
$f->unlink or $log->push, return undef;
|
|
}
|
|
if (! $keep && ! rmdir($dir->getpath)) {
|
|
my $errstr = "$!";
|
|
if (! -e $dir->getpath) {
|
|
return 1;
|
|
}
|
|
$log->put("rmdir failed: $errstr")->push($dir);
|
|
return undef;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
1;
|
|
# vim:set sw=4:
|