Show
Ignore:
Timestamp:
12/16/07 00:35:04 (7 years ago)
Author:
typester
Message:

時刻周り、権限周り実装強化。emacsでもちゃんと編集できるようになったはず

Location:
lang/perl/Fuse-Hatena/trunk
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • lang/perl/Fuse-Hatena/trunk

  • lang/perl/Fuse-Hatena/trunk/lib/Fuse/Hatena/Base.pm

    r3155 r3171  
    4242        map { $_ => $bind->("fuse_$_") } 
    4343            qw/getattr readlink getdir mknod mkdir unlink rmdir symlink rename link 
    44                chmod chown truncate utime open read write statfs flush release fsync 
    45                setxattr getxattr listxattr removexattr/, 
     44               chmod chown truncate utime open read write statfs/, 
    4645    ); 
    4746} 
     
    5049    my ($self, $path) = @_; 
    5150 
    52     my $file = $self->files; 
    53     my @path = grep {$_} split '/', $path; 
    54  
    55     return $file unless @path; 
    56  
    57     while (my $p = shift @path) { 
    58         if (@path) { 
    59             $file = $file->{$p}; 
     51    my $file = $self->{files}; 
     52    my @path = grep {$_} split '/', $path; 
     53 
     54    while (my $p = shift @path) { 
     55        if (@path) { 
     56            $file = $file->{$p}; 
     57            return unless defined $file and ref $file eq 'HASH'; 
    6058        } 
    6159        else { 
     
    6462    } 
    6563 
    66     -ENOENT(); 
     64    return $self->{files}; 
    6765} 
    6866 
    6967sub default_attr { 
    70     my ($self, $file) = @_; 
     68    my ($self, $path) = @_; 
     69 
     70    my $file  = $self->find($path); 
     71    my $mtime = $self->{mounttime} ||= time; 
    7172 
    7273    my $mode 
    7374        = ref($file) eq 'HASH'   ? S_IFDIR | 0755 
    7475        : ref($file) eq 'SCALAR' ? S_IFLNK | 0777 
    75         :                          S_IFREG | 0644; 
    76  
    77     return ( 
    78         0, 0,    # $dev, $ino, 
    79         $mode, 
    80         1,       # $nlink, see fuse.sourceforge.net/wiki/index.php/FAQ 
    81         $>, $) + 0,    # $uid, $gid, 
    82         0,             # $rdev, 
    83         ref($file) ? 1 : length $file || 0,    # $size, 
    84         $self->{mounttime}, $self->{mounttime}, 
    85         $self->{mounttime},               # actually $atime, $mtime, $ctime, 
    86         1024, 1,                          # $blksize, $blocks, 
     76        : ref($file) eq ''       ? S_IFREG | 0644 
     77        :                          S_IFREG | 0000; 
     78 
     79    $mode = S_IFREG | 0200 unless defined $file; 
     80 
     81    my $size = ref($file) ? 1 : defined($file) ? length($file) : 0; 
     82 
     83    return( 
     84        0, 0, $mode, 1, $>, $)+0, 0, $size, $mtime, $mtime, $mtime, 1024, 1 
    8785    ); 
    8886} 
    8987 
     88sub attr { 
     89    my ($self, $path, $attrs) = @_; 
     90 
     91    my %keys = do { 
     92        my $i = 0; 
     93        map { $_ => $i++ } qw/dev ino mode nlink uid gud rdev 
     94            size atime mtime ctime blksize blocks/; 
     95    }; 
     96 
     97    my $attr = $self->{attrs}{$path} || [ $self->default_attr($path) ]; 
     98    if ($attrs) { 
     99        while (my ($k,$v) = each %$attrs) { 
     100            $attr->[ $keys{$k} ] = $v; 
     101        } 
     102    } 
     103 
     104    @$attr; 
     105} 
     106 
    90107sub fuse_getattr { 
    91108    my ($self, $path) = @_; 
    92  
    93109    my $file = $self->find($path); 
    94110    return -ENOENT() unless defined $file; 
    95111 
    96     my $attr = $self->{attrs}{$path}; 
    97     $attr ? @$attr : $self->default_attr($file); 
     112    $self->attr($path); 
    98113} 
    99114 
    100115sub fuse_getdir { 
    101116    my ($self, $path) = @_; 
    102  
    103     my $file = $self->find($path); 
    104     return -ENOSYS() unless defined $file; 
    105     return -ENOENT() unless ref $file eq 'HASH'; 
    106  
    107     (qw/. ../, sort( keys %$file ), 0); 
     117    my $dir = $self->find($path); 
     118 
     119    return -ENOENT() unless defined $dir; 
     120    return -ENOENT() unless ref $dir eq 'HASH'; 
     121 
     122    (qw/. ../, sort(keys %$dir), 0); 
    108123} 
    109124 
    110125sub fuse_open { 
    111     my ($self, $path, $flags) = @_; 
    112  
    113     my $file = $self->find($path); 
    114     return -ENOSYS() unless defined $file; 
    115 #    return -EBADF() unless $flags & O_ACCMODE; 
    116  
    117     if (ref($file) eq 'HASH') { 
    118         return -EISDIR(); 
    119     } 
    120     else { 
    121         return 0; 
    122     } 
     126    my ($self, $path, $mode) = @_; 
     127    my $file = $self->find($path); 
     128 
     129#    return -EBADF() unless defined($file) or ($mode & O_ACCMODE()); 
     130    return ref $file eq 'HASH' ? -EISDIR() : ref $file eq '' ? 0 : -ENOSYS(); 
    123131} 
    124132 
     
    127135 
    128136    my $file = $self->find($path); 
     137 
    129138    return -ENOENT() unless defined $file; 
    130139    return -ENOENT() if ref $file; 
    131140 
     141    $self->attr($path => { atime => time }); 
     142 
    132143    if ($offset > length $file) { 
    133144        return -EINVAL(); 
     
    141152} 
    142153 
    143 sub fuse_release { 0 } 
    144  
    145 sub fuse_flush { 0 } 
    146  
    147 sub fuse_utime { 0 } 
    148  
    149154sub fuse_write { 
    150155    my ($self, $path, $buf, $offset) = @_; 
    151156 
    152     my $date; 
    153     my $file = $self->{files}; 
    154  
    155     my @p = grep { $_ } split '/', $path; 
    156     while (my $p = shift @p) { 
    157         if (@p) { 
    158             $file = $file->{$p}; 
    159         } 
    160         else { 
    161             my $len = length $file->{$p}; 
    162             if ($offset > $len) { 
    163                 $file->{$p} .= "\0" x ($offset - $len); 
     157    my $file = $self->find($path); 
     158    return -ENOENT() unless defined $file; 
     159    return -ENOSYS() unless ref $file eq ''; 
     160#    return -ENOSYS() unless 書き込み権限ないとき 
     161 
     162    $file = $self->{files}; 
     163    my @path = grep {$_} split '/', $path; 
     164 
     165    while (my $p = shift @path) { 
     166        if (@path) { 
     167            $file = $file->{$p}; 
     168            return -ENOENT() unless defined $file and ref $file eq 'HASH'; 
     169        } 
     170        else { 
     171            return -EINVAL() unless ref $file->{$p} eq ''; 
     172 
     173            if ($offset > length($file->{$p})) { 
     174                $file->{$p} .= "\0" x ($offset - length $file->{$p}); 
    164175            } 
    165             substr( $file->{$p}, $offset ) = $buf; 
    166         } 
    167     } 
    168  
    169     length $buf; 
    170 } 
    171  
    172 sub fuse_mknod { 
    173     my ($self, $path) = @_; 
    174  
    175     my $file = $self->{files}; 
    176     for my $p (split '/', $path) { 
    177         next if $p eq ''; 
    178  
    179         unless (exists $file->{$p}) { 
    180             $file->{$p} = ''; 
    181             return 0; 
    182         } 
    183  
    184         $file = $file->{$p}; 
    185     } 
    186  
    187     -EEXIST(); 
    188 } 
    189  
    190 sub fuse_mkdir { 
    191     my ($self, $path) = @_; 
    192  
    193     my $file = $self->{files}; 
    194     for my $p (split '/', $path) { 
    195         next if $p eq ''; 
    196  
    197         unless (exists $file->{$p}) { 
    198             $file->{$p} = {}; 
    199             return 0; 
    200         } 
    201  
    202         $file = $file->{$p}; 
    203     } 
    204  
    205     -EEXIST(); 
     176            substr($file->{$p}, $offset) = $buf; 
     177        } 
     178    } 
     179    $self->attr($path => { mtime => time }); 
     180 
     181    length($buf); 
     182} 
     183 
     184sub fuse_readlink { 
     185    my ($self, $path) = @_; 
     186 
     187    my $file = $self->find($path); 
     188    return -EINVAL() unless ref $file eq 'SCALAR'; 
     189 
     190    $$file; 
    206191} 
    207192 
     
    209194    my ($self, $path) = @_; 
    210195 
    211     my $date; 
    212     my $file = $self->{files}; 
    213  
    214     my @p = grep { $_ } split '/', $path; 
    215     while (my $p = shift @p) { 
    216         $date .= $p; 
    217         if (@p) { 
    218             $file = $file->{$p}; 
     196    my $file = $self->{files}; 
     197    my @path = grep {$_} split '/', $path; 
     198 
     199    while (my $p = shift @path) { 
     200        if (@path) { 
     201            $file = $file->{$p}; 
     202            return -ENOENT() unless defined $file and ref $file eq 'HASH'; 
    219203        } 
    220204        else { 
    221205            delete $file->{$p}; 
    222             return 0; 
    223         } 
    224     } 
    225  
    226     -ENOENT(); 
    227 } 
    228  
    229 sub fuse_rmdir { 
    230     my ($self, $path) = @_; 
    231  
    232     my $file = $self->{files}; 
    233     my @p = grep { $_ } split '/', $path; 
    234     while (my $p = shift @p) { 
    235         if (@p) { 
    236             $file = $file->{$p}; 
    237         } 
    238         else { 
    239             delete $file->{$p}; 
     206            delete $self->{attrs}{$path}; 
     207            return 0; 
     208        } 
     209    } 
     210 
     211    -ENOENT(); 
     212} 
     213 
     214sub fuse_symlink { 
     215    my ($self, $target, $path) = @_; 
     216 
     217    my $file = $self->{files}; 
     218    my @path = grep {$_} split '/', $path; 
     219 
     220    while (my $p = shift @path) { 
     221        if (@path) { 
     222            $file = $file->{$p}; 
     223            return -ENOENT() unless defined $file and ref $file eq 'HASH'; 
     224        } 
     225        else { 
     226            if (exists $file->{$p}) { 
     227                return -EEXIST(); 
     228            } 
     229            else { 
     230                $file->{$p} = \$target; 
     231                return 0; 
     232            } 
     233        } 
     234    } 
     235 
     236    -ENOENT(); 
     237} 
     238 
     239sub fuse_rename { 
     240    my ($self, $old, $new) = @_; 
     241 
     242    return -EEXIST() if $self->find($new); 
     243 
     244    my $file = $self->{files}; 
     245    my @path = grep {$_} split '/', $new; 
     246 
     247    while (my $p = shift @path) { 
     248        if (@path) { 
     249            $file = $file->{$p}; 
     250        } 
     251        else { 
     252            delete $self->{attrs}{$old}; 
     253            $old = delete $file->{$p}; 
     254        } 
     255    } 
     256 
     257    $file = $self->{files}; 
     258    @path = grep {$_} split '/', $new; 
     259 
     260    while (my $p = shift @path) { 
     261        if (@path) { 
     262            $file = $file->{$p}; 
     263            return -ENOENT() unless defined $file and ref $file eq 'HASH'; 
     264        } 
     265        else { 
     266            $file->{$p} = $old; 
    240267            return 0; 
    241268        } 
     
    248275    my ($self, $path, $mode) = @_; 
    249276 
    250     my $attr = $self->{attrs}{$path} || [$self->default_attr]; 
    251     $attr->[2] = $mode; 
    252  
    253     $self->{attrs}{$path} = $attr; 
     277    my $file = $self->find($path); 
     278    return -ENOENT() unless defined $file; 
     279 
     280    $mode 
     281        = ref($file) eq 'HASH'   ? S_IFDIR | $mode 
     282        : ref($file) eq 'SCALAR' ? S_IFLNK | $mode 
     283        :                          S_IFREG | $mode; 
     284 
     285    $self->attr($path, { mode => $mode }); 
    254286 
    255287    0; 
    256288} 
    257289 
    258 sub fuse_readlink { 
    259     my ($self, $path) = @_; 
    260  
    261     my $file = $self->find($path); 
    262     return -ENOENT() unless defined $file; 
    263     return -EINVAL() unless ref $file eq 'SCALAR'; 
    264  
    265     $$file; 
    266 } 
    267  
    268 sub fuse_symlink { 
    269     my ($self, $target, $path) = @_; 
    270  
    271     my $file = $self->{files}; 
    272     for my $p (split '/', $path) { 
    273         next if $p eq ''; 
    274  
    275         unless (exists $file->{$p}) { 
    276             $file->{$p} = \$target; 
    277             return 0; 
    278         } 
    279  
    280         $file = $file->{$p}; 
    281     } 
    282  
    283     -EEXIST(); 
    284 } 
    285  
    286 sub fuse_statfs { (255,1,1,1,1,2) } 
     290sub fuse_truncate { 
     291    my ($self, $path, $offset) = @_; 
     292 
     293    my $file = $self->{files}; 
     294    my @path = grep {$_} split '/', $path; 
     295 
     296    while (my $p = shift @path) { 
     297        if (@path) { 
     298            $file = $file->{$p}; 
     299            return -ENOENT() unless defined $file and ref $file eq 'HASH'; 
     300        } 
     301        else { 
     302            return -ENOENT() unless ref $file->{$p} eq ''; 
     303            $file->{$p} = substr($file->{$p}, 0, $offset); 
     304            return 0; 
     305        } 
     306    } 
     307 
     308    -ENOSYS(); 
     309} 
     310 
     311sub fuse_utime { 
     312    my ($self, $path, $atime, $mtime) = @_; 
     313 
     314    $self->attr($path => { atime => $atime, mtime => $mtime }); 
     315 
     316    0; 
     317} 
     318 
     319sub fuse_mkdir { 
     320    my ($self, $path, $mode) = @_; 
     321 
     322    my $file = $self->{files}; 
     323    my @path = grep {$_} split '/', $path; 
     324 
     325    while (my $p = shift @path) { 
     326        if (@path) { 
     327            $file = $file->{$p}; 
     328            return -ENOENT() unless defined $file and ref $file eq 'HASH'; 
     329        } 
     330        else { 
     331            return -EEXIST() if defined $file->{$p}; 
     332 
     333            $file->{$p} = {}; 
     334            $self->attr( $path => { mode => S_IFDIR | $mode } ); 
     335            return 0; 
     336        } 
     337    } 
     338 
     339    -ENOENT(); 
     340} 
     341 
     342sub fuse_rmdir { 
     343    my ($self, $path) = @_; 
     344 
     345    my $file = $self->{files}; 
     346    my @path = grep {$_} split '/', $path; 
     347 
     348    while (my $p = shift @path) { 
     349        if (@path) { 
     350            $file = $file->{$p}; 
     351            return -ENOENT() unless defined $file and ref $file eq 'HASH'; 
     352        } 
     353        else { 
     354            delete $file->{$p}; 
     355            delete $self->{attrs}{$path}; 
     356            return 0; 
     357        } 
     358    } 
     359 
     360    -ENOSYS(); 
     361} 
     362 
     363sub fuse_mknod { 
     364    my ($self, $path) = @_; 
     365 
     366    my $file = $self->{files}; 
     367    my @path = grep {$_} split '/', $path; 
     368 
     369    while (my $p = shift @path) { 
     370        if (@path) { 
     371            $file = $file->{$p}; 
     372            return -ENOENT() unless defined $file and ref $file eq 'HASH'; 
     373        } 
     374        else { 
     375            return -EEXIST() if defined $file->{$p}; 
     376            $file->{$p} = ''; 
     377            return 0; 
     378        } 
     379    } 
     380 
     381    -ENOENT(); 
     382} 
     383 
     384sub fuse_statfs { 255, 1000000, 500000, 1000000, 500000, 4096 } 
     385 
     386sub fuse_release {0} 
     387 
     388sub fuse_flush {0} 
    287389 
    2883901;