# Copyright (c) 2014, cPanel, Inc.
# All rights reserved.
# http://cpanel.net/
#
# This is free software; you can redistribute it and/or modify it under the same
# terms as Perl itself. See the LICENSE file for further details.
package Filesys::POSIX::FdTable;
use strict;
use warnings;
use Filesys::POSIX::Error qw(throw);
=head1 NAME
Filesys::POSIX::FdTable - File descriptor table
=head1 DESCRIPTION
This internal module used by Filesys::POSIX handles the allocation and tracking
of numeric file descriptors associated with inodes opened for I/O. It does not
intend to expose any public interfaces.
=head1 METHODS
=over
=item C<Filesys::POSIX::FdTable-E<gt>new>
Create a new file descriptor table object. Returns a blessed hash.
=cut
sub new {
return bless {}, shift;
}
=item C<$fd_table-E<gt>open($inode, $flags)>
Asks the C<$inode> object to open and return a L<Filesys::POSIX::IO::Handle>
object. Accepts flags as defined in L<Filesys::POSIX::Bits>. A reference to
the inode, file handle, flags passed will be stored.
Returns a unused file descriptor number greater than 2, unique to the current
file descriptor table, upon success. Possible exceptions may be thrown:
=over
=item * ENODEV (No such device or address)
Could not open a file handle for the inode passed.
=back
=cut
sub open {
my ( $self, $inode, $flags ) = @_;
my $fd = 2;
my $handle = $inode->open($flags);
$! = 0;
throw &Errno::ENODEV unless $handle;
foreach ( sort { $a <=> $b } ( $fd, keys %$self ) ) {
next if $self->{ $fd = $_ + 1 };
last;
}
$self->{$fd} = {
'inode' => $inode,
'handle' => $handle,
'flags' => $flags
};
return $fd;
}
=item C<$fd_table-E<gt>lookup($fd)>
Given a file descriptor number, return the file descriptor table entry stored;
such an object contains an inode reference, a file handle reference, and the
flags with which the file was opened. Possible exceptions include:
=over
=item * EBADF (Bad file descriptor)
No handle found for the given file descriptor.
=back
=cut
sub lookup {
my ( $self, $fd ) = @_;
$! = 0;
my $entry = $self->{$fd} or throw &Errno::EBADF;
return $entry;
}
=item C<$fd_table-E<gt>close($fd)>
Close the file handle corresponding to the given file descriptor, and remove the
file descriptor from the table, freeing it for future reallocation.
=cut
sub close {
my ( $self, $fd ) = @_;
my $entry = $self->{$fd} or return;
$entry->{'handle'}->close;
delete $self->{$fd};
}
=item C<$fd_table-E<gt>list>
Return a list of all file descriptor numbers currently allocated.
=cut
sub list {
my ($self) = @_;
return keys %$self;
}
=back
=cut
1;
__END__
=head1 AUTHOR
Written by Xan Tronix <xan@cpan.org>
=head1 CONTRIBUTORS
=over
=item Rikus Goodell <rikus.goodell@cpanel.net>
=item Brian Carlson <brian.carlson@cpanel.net>
=back
=head1 COPYRIGHT
Copyright (c) 2014, cPanel, Inc. Distributed under the terms of the Perl
Artistic license.