Unix-ConfigFile

 view release on metacpan or  search on metacpan

ConfigFile.pm  view on Meta::CPAN


# Preloaded methods go here.

# Create a new ConfigFile (or, more likely, a ConfigFile subclass) object.
# Opens the specified file and calls the read method (which will be located
# in the subclass package) to initialize the object data structures
sub new {
    my ($pkg, $filename, %opt) = @_;

    # Initialize the object reference
    my $this = {
	filename    =>	$filename,
	handle	    =>	undef,
	locked	    =>	0,
	lockfh	    =>	undef,
	lockfile    =>	"$filename.lock",
	locking	    =>	"dotlock",
	mode	    =>	"r+",
	seq	    =>	[ ]
    };
    bless $this, $pkg;

    # Set options
    $this->lockfile($opt{lockfile}) if defined $opt{lockfile};
    $this->locking($opt{locking}) if defined $opt{locking};
    $this->mode($opt{mode}) if defined $opt{mode};

    # Get a filehandle
    my $fh = new IO::File $this->filename, $this->mode;
    return undef unless defined($fh);
    $this->fh($fh);

    # Do file locking - this must happen before read is called or we could
    # end up with stale data in memory
    if ($this->mode eq "r") {
	$this->lock("shared") or return undef;
    }
    else {
	$this->lock() or return undef;
    }

    # Initialize object structure from the file
    if (exists $opt{readopts}) {
	$this->read($this->fh, $opt{readopts}) or return undef;
    }
    else {
	$this->read($this->fh) or return undef;
    }
    return $this;
}


# Commit in-memory changes to disk
sub commit {
    my ($this, %opt) = @_;

    return 0 if $this->mode eq "r";
    my $tempname = $this->filename . ".tmp." . $$;
    my $fh = new IO::File ">$tempname" or return 0;
    my ($mode, $uid, $gid) = (stat $this->fh)[2,4,5];
    chown $uid, $gid, $tempname;
    chmod $mode, $tempname;
    if (exists $opt{writeopts}) {
	$this->write($fh, $opt{writeopts}) or return 0;
    }
    else {
	$this->write($fh) or return 0;
    }
    undef $fh;
    if (defined $opt{backup}) {
	rename $this->filename, $this->filename . $opt{backup};
    }
    return rename $tempname, $this->filename;
}


# This method is absolutely necessary to prevent leftover lock files
sub DESTROY {
    my $this = shift;

    $this->unlock() or croak "Can't unlock file: $!";
    $this->fh->close();
}


# Filename accessor
sub filename {
    my $this = shift;
    @_ ? $this->{filename} = shift : $this->{filename};
}


# Filehandle accessor
sub fh {
    my $this = shift;
    @_ ? $this->{handle} = shift : $this->{handle};
}


# Locking method accessor
sub locking {
    my $this = shift;

    return $this->{locking} unless @_;
    my $lockmethod = shift;
    return undef unless grep { $lockmethod eq $_ } qw(flock dotlock none);
    $this->{locking} = $lockmethod;
}


# Lock filehandle accessor
sub lockfh {
    my $this = shift;
    @_ ? $this->{lockfh} = shift : $this->{lockfh};
}


# Lock file name accessor
sub lockfile {
    my $this = shift;
    @_ ? $this->{lockfile} = shift : $this->{lockfile};



( run in 1.309 second using v1.01-cache-2.11-cpan-4e7a2411597 )