/[fuse_dbi]/trunk/fuse_dbi.pl
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /trunk/fuse_dbi.pl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6 - (hide annotations)
Wed Aug 4 16:17:09 2004 UTC (17 years, 9 months ago) by dpavlin
File MIME type: text/plain
File size: 6113 byte(s)
first try at making it writable

1 dpavlin 1 #!/usr/bin/perl
2    
3 dpavlin 6 use POSIX qw(ENOENT EISDIR EINVAL O_RDWR);
4 dpavlin 1 use Fuse;
5    
6     use DBI;
7     use strict;
8    
9     my $sql_filenames = q{
10     select
11 dpavlin 3 oid as id,
12     namespace||'/'||name||' ['||oid||']' as filename,
13 dpavlin 1 length(template) as size,
14     iseditable as writable
15     from template ;
16     };
17    
18 dpavlin 6 my $sql_read = q{
19 dpavlin 1 select template
20 dpavlin 6 from template
21     where oid = ?;
22 dpavlin 1 };
23    
24 dpavlin 6 my $sql_update = q{
25     update template
26     set template = ?
27     where oid = ?;
28     };
29 dpavlin 1
30 dpavlin 6
31 dpavlin 1 my $connect = "DBI:Pg:dbname=webgui";
32    
33     my $dbh = DBI->connect($connect,"","") || die $DBI::errstr;
34    
35     print STDERR "$sql_filenames\n";
36    
37     my $sth_filenames = $dbh->prepare($sql_filenames) || die $dbh->errstr();
38     $sth_filenames->execute() || die $sth_filenames->errstr();
39    
40 dpavlin 6 my $sth_read = $dbh->prepare($sql_read) || die $dbh->errstr();
41     my $sth_update = $dbh->prepare($sql_update) || die $dbh->errstr();
42 dpavlin 1
43     print "#",join(",",@{ $sth_filenames->{NAME} }),"\n";
44    
45     my $ctime_start = time();
46    
47     my (%files) = (
48     '.' => {
49     type => 0040,
50     mode => 0755,
51     },
52     # a => {
53     # cont => "File 'a'.\n",
54     # type => 0100,
55     # ctime => time()-2000
56     # },
57     );
58    
59     my %dirs;
60    
61     while (my $row = $sth_filenames->fetchrow_hashref() ) {
62     $files{$row->{'filename'}} = {
63     size => $row->{'size'},
64     mode => $row->{'writable'} ? 0644 : 0444,
65     id => $row->{'id'} || 99,
66     };
67    
68     my $d;
69     foreach (split(m!/!, $row->{'filename'})) {
70     # first, entry is assumed to be file
71     if ($d) {
72     $files{$d} = {
73     size => $dirs{$d}++,
74     mode => 0755,
75     type => 0040
76     };
77     $files{$d.'/.'} = {
78     mode => 0755,
79     type => 0040
80     };
81     $files{$d.'/..'} = {
82     mode => 0755,
83     type => 0040
84     };
85     }
86     $d .= "/" if ($d);
87     $d .= "$_";
88     }
89     }
90    
91     print scalar (keys %dirs), " dirs:",join(" ",keys %dirs),"\n";
92    
93     sub filename_fixup {
94     my ($file) = shift;
95     $file =~ s,^/,,;
96     $file = '.' unless length($file);
97     return $file;
98     }
99    
100     sub e_getattr {
101     my ($file) = filename_fixup(shift);
102     $file =~ s,^/,,;
103     $file = '.' unless length($file);
104     return -ENOENT() unless exists($files{$file});
105     my ($size) = $files{$file}{size} || 1;
106     my ($dev, $ino, $rdev, $blocks, $gid, $uid, $nlink, $blksize) = (0,0,0,1,0,0,1,1024);
107     my ($atime, $ctime, $mtime);
108     $atime = $ctime = $mtime = $files{$file}{ctime} || $ctime_start;
109    
110     my ($modes) = (($files{$file}{type} || 0100)<<9) + $files{$file}{mode};
111    
112     # 2 possible types of return values:
113     #return -ENOENT(); # or any other error you care to
114     #print(join(",",($dev,$ino,$modes,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks)),"\n");
115     return ($dev,$ino,$modes,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks);
116     }
117    
118     sub e_getdir {
119     my ($dirname) = shift;
120     $dirname =~ s!^/!!;
121     # return as many text filenames as you like, followed by the retval.
122     print((scalar keys %files)." files total\n");
123     my %out;
124     foreach (keys %files) {
125     my $f = $_;
126     $f =~ s/^\E$dirname\Q//;
127     $f =~ s/^\///;
128     if ($dirname) {
129 dpavlin 2 $out{$f}++ if (/^\E$dirname\Q/ && $f =~ /^[^\/]+$/);
130 dpavlin 1 } else {
131     $out{$f}++ if ($f =~ /^[^\/]+$/);
132     }
133     print "f: $_ -> $f\n";
134     }
135     if (! %out) {
136     $out{'no files? bug?'}++;
137     }
138     print scalar keys %out," files found for '$dirname': ",keys %out,"\n";
139     return (keys %out),0;
140     }
141    
142 dpavlin 6 my $in_transaction = 0;
143    
144 dpavlin 1 sub e_open {
145     # VFS sanity check; it keeps all the necessary state, not much to do here.
146 dpavlin 6 my $file = filename_fixup(shift);
147     my $flags = shift;
148    
149 dpavlin 1 return -ENOENT() unless exists($files{$file});
150     return -EISDIR() unless exists($files{$file}{id});
151 dpavlin 6
152     if (! $in_transaction) {
153     # begin transaction
154     if (! $dbh->begin_work) {
155     print "transaction begin: ",$dbh->errstr;
156     return -ENOENT();
157     }
158     }
159     $in_transaction++;
160     print "files opened: $in_transaction\n";
161    
162 dpavlin 1 if (!exists($files{$file}{cont})) {
163 dpavlin 6 $sth_read->execute($files{$file}{id}) || die $sth_read->errstr;
164     $files{$file}{cont} = $sth_read->fetchrow_array;
165 dpavlin 1 }
166 dpavlin 3 print "open '$file' ",length($files{$file}{cont})," bytes\n";
167 dpavlin 1 return 0;
168     }
169    
170     sub e_read {
171 dpavlin 3 # return an error numeric, or binary/text string.
172     # (note: 0 means EOF, "0" will give a byte (ascii "0")
173     # to the reading program)
174 dpavlin 1 my ($file) = filename_fixup(shift);
175     my ($buf,$off) = @_;
176 dpavlin 3
177 dpavlin 1 return -ENOENT() unless exists($files{$file});
178 dpavlin 3
179     my $len = length($files{$file}{cont});
180    
181     print "read '$file' [$len bytes] offset $off length $buf\n";
182    
183     return -EINVAL() if ($off > $len);
184     return 0 if ($off == $len);
185    
186     $buf = $len-$off if ($off+$buf > $len);
187    
188 dpavlin 1 return substr($files{$file}{cont},$off,$buf);
189     }
190    
191 dpavlin 6 sub clear_cont {
192     print "invalidate all cached content\n";
193     foreach my $f (keys %files) {
194     delete $files{$f}{cont};
195     }
196     }
197    
198    
199     sub update_db {
200     my $file = shift || die;
201    
202     if (!$sth_update->execute($files{$file}{cont},$files{$file}{id})) {
203     print "update problem: ",$sth_update->errstr;
204     $dbh->rollback;
205     clear_cont;
206     $dbh->begin_work;
207     return 0;
208     } else {
209     if ($dbh->commit) {
210     print "commit problem: ",$sth_update->errstr;
211     $dbh->rollback;
212     clear_cont;
213     $dbh->begin_work;
214     return 0;
215     }
216     print "updated '$file' [",$files{$file}{id},"]\n";
217     }
218     return 1;
219     }
220    
221     sub e_write {
222     my $file = filename_fixup(shift);
223     my ($buf,$off) = @_;
224    
225     return -ENOENT() unless exists($files{$file});
226    
227     my $len = length($files{$file}{cont});
228    
229     print "write '$file' [$len bytes] offset $off length $buf\n";
230    
231     $files{$file}{cont} =
232     substr($files{$file}{cont},0,$off) .
233     $buf .
234     substr($files{$file}{cont},$off+length($buf));
235    
236     if (! update_db($file)) {
237     return -ENOSYS();
238     } else {
239     return length($buf);
240     }
241     }
242    
243     sub e_truncate {
244     my $file = filename_fixup(shift);
245     my $size = shift;
246    
247     $files{$file}{cont} = substr($files{$file}{cont},0,$size);
248     return 0
249     };
250    
251    
252     sub e_utime {
253     my ($atime,$mtime,$file) = @_;
254     $file = filename_fixup($file);
255    
256     return -ENOENT() unless exists($files{$file});
257    
258     $files{$file}{time} = $mtime;
259     return 0;
260     }
261    
262 dpavlin 1 sub e_statfs { return 255, 1, 1, 1, 1, 2 }
263    
264     # If you run the script directly, it will run fusermount, which will in turn
265     # re-run this script. Hence the funky semantics.
266     my ($mountpoint) = "";
267     $mountpoint = shift(@ARGV) if @ARGV;
268     Fuse::main(
269     mountpoint=>$mountpoint,
270     getattr=>\&e_getattr,
271     getdir=>\&e_getdir,
272     open=>\&e_open,
273     statfs=>\&e_statfs,
274     read=>\&e_read,
275 dpavlin 6 write=>\&e_write,
276     utime=>\&e_utime,
277     truncate=>\&e_truncate,
278 dpavlin 1 debug=>1,
279     );

Properties

Name Value
svn:executable

  ViewVC Help
Powered by ViewVC 1.1.26