Все задачи

Созидательный труд-5

30 Sep 2013

Программист победил race condition в модуле MkDir из предыдущей задачи:

package MkDir5;

use strict;
use warnings;

=head1 NAME

MkDir5 -- рекурсивное создание каталогов

=head1 SYNOPSIS

    use MkDir5;
    MkDir5::mkdir_recursive("test/a");
    MkDir5::mkdir_recursive("/tmp/test/b");

=head1 DESCRIPTION

Модуль предоставляет функцию mkdir_recursive для рекурсивного создания каталогов.

Модуль предназначен для Unix-подобных систем с разделителем в именах каталогов "/" и корневым каталогом /.

=cut

sub _mkdir
{
    my ($dir) = @_;

    unless(-d $dir){
        unless(mkdir $dir){
            unless(-d $dir){
                die "Can't create dir $dir: $!";
            }
        }
    } 
}

sub mkdir_recursive
{
    my $path = shift or die;

    my @parts = split "/", $path;

    my $dir = shift @parts;
    _mkdir $dir unless $dir eq '';
    for my $d (@parts){
        $dir .= "/$d";
        _mkdir $dir;
    }
}

1;

Файл можно скачать: MkDir5.pm .

Неужели здесь еще остались ошибки?

Увы, когда скрипту все-таки не удается создать каталог, он выводит какие-то странные сообщения…

Можно скачать пример использования и убедиться своими глазами.

Подсказка

Показать

Например, если обычным пользователем попытаться создать каталог /roooot, ожидаемо было бы увидеть ошибку Permission denied, но вместо этого выдается No such file or directory.

Подсказка-2

Показать

perldoc -v '$!'

Разоблачение

Показать

Если оператор -d не находит указанный каталог, он заполняет переменную $!, и к моменту выполнения die "Can't create dir $dir: $!"; эта переменная уже не содержит информации о том, почему не прошел mkdir.

Чтобы всегда видеть правильные сообщения, стоило бы сохранять сообщение об ошибке в обыкновенной пользовательской переменной:

unless(-d $dir){ 
    unless(mkdir $dir){
        my $mkdir_err = $!;
        unless(-d $dir){
            die "Can't create dir: $mkdir_err";
        }
    }
}

На этом заканчивается эпопея нашего программиста с рекурсивным созданием каталогов.

Впрочем, кто знает: возможно, через полгода ему придется исправлять даже этот “хороший” код.