/[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 8 - (hide annotations)
Sat Aug 7 15:16:50 2004 UTC (19 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 6105 byte(s)
better output, read fixes, ctime preserved (so that vi won't complain that
your file changed if you save changes and try that again)

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

Properties

Name Value
svn:executable

  ViewVC Help
Powered by ViewVC 1.1.26