File: hppfs.pm

package info (click to toggle)
uml-utilities 20070815.4-2.1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 752 kB
  • sloc: ansic: 3,392; perl: 1,277; makefile: 239; exp: 129; sh: 122
file content (131 lines) | stat: -rw-r--r-- 2,608 bytes parent folder | download | duplicates (9)
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
# 
# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
# Licensed under the GPL
#

package hppfs;

use Socket;
use IO::Select;

use strict;

sub new {
    my $class = shift;
    my $base = shift;

    !defined($base) and $base = ".";
    my $me = { files => { }, handles => { }, base => $base };

    bless($me, $class);
    return($me);
}

sub add {
    my $me = shift;

    while(@_){
	my $file = shift;
	my $handler = shift;

	$me->{files}->{$file} = $handler;
    }
}

sub prepare {
    my $me = shift;
    my $dir = shift;
    my $file = shift;

    my $full = $me->{base} . "/proc/$dir";
    if(! -d $full){
	unlink $full;
	my $out = `mkdir -p $full 2>&1`;
	$? and die "mkdir '$full' failed : $out";
    }

    my $out = `chmod 755 $full 2>&1`;
    $? and die "chmod 755 $full failed : $out";

    defined($file) and unlink "$full/$file";
    return("$full/$file");
}

sub setup_sock {
    my ($me, $file, undef, $mode) = @_;

    my $full = $me->prepare($file, $mode);

    my $sock = sockaddr_un($full);
    !defined($sock) and die "sockaddr_un of '$sock' failed : $!";

    !defined(socket(my $fh, AF_UNIX, SOCK_STREAM, 0)) and 
	die "socket failed : $!";

    !defined(bind($fh, $sock)) and die "bind failed : $!";
    my $out = `chmod 777 $full 2>&1`;
    $? ne 0 and die "'chmod 777 $full' failed : $!";

    !defined(listen($fh, 5)) and die "listen failed : $!";

    $me->{select}->add(\*$fh);
    $me->{handles}->{fileno(\*$fh)} = $file;
}

sub setup_remove {
    my ($me, $file) = @_;

    my $full = $me->prepare($file);

    my $out = `touch $full/remove 2>&1`;
    $? != 0 and die "touch $full/remove failed : $out";
}

sub handler {
    my $me = shift;
    $me->{select} = IO::Select->new();

    foreach my $file (keys(%{$me->{files}})){
	my $handler = $me->{files}->{$file};
	if(ref($handler) eq "ARRAY"){
	    $me->setup_sock($file, @$handler);
	}
	elsif($handler eq "remove"){
	    $me->setup_remove($file);
	}
	else {
	    die "Bad handler for '$file'";
	}
    }

    while(1){
	my @ready = $me->{select}->can_read();
	
	foreach my $sock (@ready){
	    my $file = $me->{handles}->{fileno($sock)};
	    !defined($file) and die "Couldn't map from socket to file";

	    !accept(CONN, $sock) and die "accept failed : $!";

	    my ($handler, $mode) = @{$me->{files}->{$file}};

	    (!defined($handler) || !defined($mode)) and 
		die "Couldn't map from file to handler";

	    my $output;

	    if($mode eq "rw"){
		my $input = join("", <CONN>);
		$output = $handler->($input);
	    }
	    else {
		$output = $handler->();
	    }

	    print CONN $output;
	    close CONN;
	}
    }
}

1;